xref: /aosp_15_r20/external/swiftshader/src/WSI/XcbSurfaceKHR.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //	http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "XcbSurfaceKHR.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "libXCB.hpp"
18*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkDeviceMemory.hpp"
19*03ce13f7SAndroid Build Coastguard Worker #include "Vulkan/VkImage.hpp"
20*03ce13f7SAndroid Build Coastguard Worker 
21*03ce13f7SAndroid Build Coastguard Worker #include <sys/ipc.h>
22*03ce13f7SAndroid Build Coastguard Worker #include <sys/shm.h>
23*03ce13f7SAndroid Build Coastguard Worker 
24*03ce13f7SAndroid Build Coastguard Worker #include <memory>
25*03ce13f7SAndroid Build Coastguard Worker 
26*03ce13f7SAndroid Build Coastguard Worker namespace vk {
27*03ce13f7SAndroid Build Coastguard Worker 
getWindowSizeAndDepth(xcb_connection_t * connection,xcb_window_t window,VkExtent2D * windowExtent,int * depth)28*03ce13f7SAndroid Build Coastguard Worker bool getWindowSizeAndDepth(xcb_connection_t *connection, xcb_window_t window, VkExtent2D *windowExtent, int *depth)
29*03ce13f7SAndroid Build Coastguard Worker {
30*03ce13f7SAndroid Build Coastguard Worker 	auto cookie = libXCB->xcb_get_geometry(connection, window);
31*03ce13f7SAndroid Build Coastguard Worker 	if(auto *geom = libXCB->xcb_get_geometry_reply(connection, cookie, nullptr))
32*03ce13f7SAndroid Build Coastguard Worker 	{
33*03ce13f7SAndroid Build Coastguard Worker 		windowExtent->width = static_cast<uint32_t>(geom->width);
34*03ce13f7SAndroid Build Coastguard Worker 		windowExtent->height = static_cast<uint32_t>(geom->height);
35*03ce13f7SAndroid Build Coastguard Worker 		*depth = static_cast<int>(geom->depth);
36*03ce13f7SAndroid Build Coastguard Worker 		free(geom);
37*03ce13f7SAndroid Build Coastguard Worker 		return true;
38*03ce13f7SAndroid Build Coastguard Worker 	}
39*03ce13f7SAndroid Build Coastguard Worker 	return false;
40*03ce13f7SAndroid Build Coastguard Worker }
41*03ce13f7SAndroid Build Coastguard Worker 
isSupported()42*03ce13f7SAndroid Build Coastguard Worker bool XcbSurfaceKHR::isSupported()
43*03ce13f7SAndroid Build Coastguard Worker {
44*03ce13f7SAndroid Build Coastguard Worker 	return libXCB.isPresent();
45*03ce13f7SAndroid Build Coastguard Worker }
46*03ce13f7SAndroid Build Coastguard Worker 
XcbSurfaceKHR(const VkXcbSurfaceCreateInfoKHR * pCreateInfo,void * mem)47*03ce13f7SAndroid Build Coastguard Worker XcbSurfaceKHR::XcbSurfaceKHR(const VkXcbSurfaceCreateInfoKHR *pCreateInfo, void *mem)
48*03ce13f7SAndroid Build Coastguard Worker     : connection(pCreateInfo->connection)
49*03ce13f7SAndroid Build Coastguard Worker     , window(pCreateInfo->window)
50*03ce13f7SAndroid Build Coastguard Worker {
51*03ce13f7SAndroid Build Coastguard Worker 	ASSERT(isSupported());
52*03ce13f7SAndroid Build Coastguard Worker 
53*03ce13f7SAndroid Build Coastguard Worker 	gc = libXCB->xcb_generate_id(connection);
54*03ce13f7SAndroid Build Coastguard Worker 	uint32_t values[2] = { 0, 0xFFFFFFFF };
55*03ce13f7SAndroid Build Coastguard Worker 	libXCB->xcb_create_gc(connection, gc, window, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, values);
56*03ce13f7SAndroid Build Coastguard Worker 
57*03ce13f7SAndroid Build Coastguard Worker 	auto shmQuery = libXCB->xcb_get_extension_data(connection, libXCB->xcb_shm_id);
58*03ce13f7SAndroid Build Coastguard Worker 	if(shmQuery->present)
59*03ce13f7SAndroid Build Coastguard Worker 	{
60*03ce13f7SAndroid Build Coastguard Worker 		auto shmCookie = libXCB->xcb_shm_query_version(connection);
61*03ce13f7SAndroid Build Coastguard Worker 		if(auto *reply = libXCB->xcb_shm_query_version_reply(connection, shmCookie, nullptr))
62*03ce13f7SAndroid Build Coastguard Worker 		{
63*03ce13f7SAndroid Build Coastguard Worker 			mitSHM = reply && reply->shared_pixmaps;
64*03ce13f7SAndroid Build Coastguard Worker 			free(reply);
65*03ce13f7SAndroid Build Coastguard Worker 		}
66*03ce13f7SAndroid Build Coastguard Worker 	}
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker 	auto geomCookie = libXCB->xcb_get_geometry(connection, window);
69*03ce13f7SAndroid Build Coastguard Worker 	if(auto *reply = libXCB->xcb_get_geometry_reply(connection, geomCookie, nullptr))
70*03ce13f7SAndroid Build Coastguard Worker 	{
71*03ce13f7SAndroid Build Coastguard Worker 		windowDepth = reply->depth;
72*03ce13f7SAndroid Build Coastguard Worker 		free(reply);
73*03ce13f7SAndroid Build Coastguard Worker 	}
74*03ce13f7SAndroid Build Coastguard Worker 	else
75*03ce13f7SAndroid Build Coastguard Worker 	{
76*03ce13f7SAndroid Build Coastguard Worker 		surfaceLost = true;
77*03ce13f7SAndroid Build Coastguard Worker 	}
78*03ce13f7SAndroid Build Coastguard Worker }
79*03ce13f7SAndroid Build Coastguard Worker 
destroySurface(const VkAllocationCallbacks * pAllocator)80*03ce13f7SAndroid Build Coastguard Worker void XcbSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
81*03ce13f7SAndroid Build Coastguard Worker {
82*03ce13f7SAndroid Build Coastguard Worker 	libXCB->xcb_free_gc(connection, gc);
83*03ce13f7SAndroid Build Coastguard Worker }
84*03ce13f7SAndroid Build Coastguard Worker 
ComputeRequiredAllocationSize(const VkXcbSurfaceCreateInfoKHR * pCreateInfo)85*03ce13f7SAndroid Build Coastguard Worker size_t XcbSurfaceKHR::ComputeRequiredAllocationSize(const VkXcbSurfaceCreateInfoKHR *pCreateInfo)
86*03ce13f7SAndroid Build Coastguard Worker {
87*03ce13f7SAndroid Build Coastguard Worker 	return 0;
88*03ce13f7SAndroid Build Coastguard Worker }
89*03ce13f7SAndroid Build Coastguard Worker 
getSurfaceCapabilities(const void * pSurfaceInfoPNext,VkSurfaceCapabilitiesKHR * pSurfaceCapabilities,void * pSurfaceCapabilitiesPNext) const90*03ce13f7SAndroid Build Coastguard Worker VkResult XcbSurfaceKHR::getSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext) const
91*03ce13f7SAndroid Build Coastguard Worker {
92*03ce13f7SAndroid Build Coastguard Worker 	if(surfaceLost)
93*03ce13f7SAndroid Build Coastguard Worker 	{
94*03ce13f7SAndroid Build Coastguard Worker 		return VK_ERROR_SURFACE_LOST_KHR;
95*03ce13f7SAndroid Build Coastguard Worker 	}
96*03ce13f7SAndroid Build Coastguard Worker 
97*03ce13f7SAndroid Build Coastguard Worker 	VkExtent2D extent;
98*03ce13f7SAndroid Build Coastguard Worker 	int depth;
99*03ce13f7SAndroid Build Coastguard Worker 	if(!getWindowSizeAndDepth(connection, window, &extent, &depth))
100*03ce13f7SAndroid Build Coastguard Worker 	{
101*03ce13f7SAndroid Build Coastguard Worker 		surfaceLost = true;
102*03ce13f7SAndroid Build Coastguard Worker 		return VK_ERROR_SURFACE_LOST_KHR;
103*03ce13f7SAndroid Build Coastguard Worker 	}
104*03ce13f7SAndroid Build Coastguard Worker 
105*03ce13f7SAndroid Build Coastguard Worker 	pSurfaceCapabilities->currentExtent = extent;
106*03ce13f7SAndroid Build Coastguard Worker 	pSurfaceCapabilities->minImageExtent = extent;
107*03ce13f7SAndroid Build Coastguard Worker 	pSurfaceCapabilities->maxImageExtent = extent;
108*03ce13f7SAndroid Build Coastguard Worker 
109*03ce13f7SAndroid Build Coastguard Worker 	setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
110*03ce13f7SAndroid Build Coastguard Worker 	return VK_SUCCESS;
111*03ce13f7SAndroid Build Coastguard Worker }
112*03ce13f7SAndroid Build Coastguard Worker 
allocateImageMemory(PresentImage * image,const VkMemoryAllocateInfo & allocateInfo)113*03ce13f7SAndroid Build Coastguard Worker void *XcbSurfaceKHR::allocateImageMemory(PresentImage *image, const VkMemoryAllocateInfo &allocateInfo)
114*03ce13f7SAndroid Build Coastguard Worker {
115*03ce13f7SAndroid Build Coastguard Worker 	if(!mitSHM)
116*03ce13f7SAndroid Build Coastguard Worker 	{
117*03ce13f7SAndroid Build Coastguard Worker 		return nullptr;
118*03ce13f7SAndroid Build Coastguard Worker 	}
119*03ce13f7SAndroid Build Coastguard Worker 
120*03ce13f7SAndroid Build Coastguard Worker 	SHMPixmap &pixmap = pixmaps[image];
121*03ce13f7SAndroid Build Coastguard Worker 	int shmid = shmget(IPC_PRIVATE, allocateInfo.allocationSize, IPC_CREAT | SHM_R | SHM_W);
122*03ce13f7SAndroid Build Coastguard Worker 	pixmap.shmaddr = shmat(shmid, 0, 0);
123*03ce13f7SAndroid Build Coastguard Worker 	pixmap.shmseg = libXCB->xcb_generate_id(connection);
124*03ce13f7SAndroid Build Coastguard Worker 	libXCB->xcb_shm_attach(connection, pixmap.shmseg, shmid, false);
125*03ce13f7SAndroid Build Coastguard Worker 	shmctl(shmid, IPC_RMID, 0);
126*03ce13f7SAndroid Build Coastguard Worker 
127*03ce13f7SAndroid Build Coastguard Worker 	int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
128*03ce13f7SAndroid Build Coastguard Worker 	int bytesPerPixel = static_cast<int>(image->getImage()->getFormat(VK_IMAGE_ASPECT_COLOR_BIT).bytes());
129*03ce13f7SAndroid Build Coastguard Worker 	int width = stride / bytesPerPixel;
130*03ce13f7SAndroid Build Coastguard Worker 	int height = allocateInfo.allocationSize / stride;
131*03ce13f7SAndroid Build Coastguard Worker 
132*03ce13f7SAndroid Build Coastguard Worker 	pixmap.pixmap = libXCB->xcb_generate_id(connection);
133*03ce13f7SAndroid Build Coastguard Worker 	libXCB->xcb_shm_create_pixmap(
134*03ce13f7SAndroid Build Coastguard Worker 	    connection,
135*03ce13f7SAndroid Build Coastguard Worker 	    pixmap.pixmap,
136*03ce13f7SAndroid Build Coastguard Worker 	    window,
137*03ce13f7SAndroid Build Coastguard Worker 	    width, height,
138*03ce13f7SAndroid Build Coastguard Worker 	    windowDepth,
139*03ce13f7SAndroid Build Coastguard Worker 	    pixmap.shmseg,
140*03ce13f7SAndroid Build Coastguard Worker 	    0);
141*03ce13f7SAndroid Build Coastguard Worker 
142*03ce13f7SAndroid Build Coastguard Worker 	return pixmap.shmaddr;
143*03ce13f7SAndroid Build Coastguard Worker }
144*03ce13f7SAndroid Build Coastguard Worker 
releaseImageMemory(PresentImage * image)145*03ce13f7SAndroid Build Coastguard Worker void XcbSurfaceKHR::releaseImageMemory(PresentImage *image)
146*03ce13f7SAndroid Build Coastguard Worker {
147*03ce13f7SAndroid Build Coastguard Worker 	if(mitSHM)
148*03ce13f7SAndroid Build Coastguard Worker 	{
149*03ce13f7SAndroid Build Coastguard Worker 		auto it = pixmaps.find(image);
150*03ce13f7SAndroid Build Coastguard Worker 		assert(it != pixmaps.end());
151*03ce13f7SAndroid Build Coastguard Worker 		libXCB->xcb_shm_detach(connection, it->second.shmseg);
152*03ce13f7SAndroid Build Coastguard Worker 		shmdt(it->second.shmaddr);
153*03ce13f7SAndroid Build Coastguard Worker 		libXCB->xcb_free_pixmap(connection, it->second.pixmap);
154*03ce13f7SAndroid Build Coastguard Worker 		pixmaps.erase(it);
155*03ce13f7SAndroid Build Coastguard Worker 	}
156*03ce13f7SAndroid Build Coastguard Worker }
157*03ce13f7SAndroid Build Coastguard Worker 
attachImage(PresentImage * image)158*03ce13f7SAndroid Build Coastguard Worker void XcbSurfaceKHR::attachImage(PresentImage *image)
159*03ce13f7SAndroid Build Coastguard Worker {
160*03ce13f7SAndroid Build Coastguard Worker }
161*03ce13f7SAndroid Build Coastguard Worker 
detachImage(PresentImage * image)162*03ce13f7SAndroid Build Coastguard Worker void XcbSurfaceKHR::detachImage(PresentImage *image)
163*03ce13f7SAndroid Build Coastguard Worker {
164*03ce13f7SAndroid Build Coastguard Worker }
165*03ce13f7SAndroid Build Coastguard Worker 
present(PresentImage * image)166*03ce13f7SAndroid Build Coastguard Worker VkResult XcbSurfaceKHR::present(PresentImage *image)
167*03ce13f7SAndroid Build Coastguard Worker {
168*03ce13f7SAndroid Build Coastguard Worker 	VkExtent2D windowExtent;
169*03ce13f7SAndroid Build Coastguard Worker 	int depth;
170*03ce13f7SAndroid Build Coastguard Worker 	// TODO(penghuang): getWindowSizeAndDepth() call needs a sync IPC, try to remove it.
171*03ce13f7SAndroid Build Coastguard Worker 	if(surfaceLost || !getWindowSizeAndDepth(connection, window, &windowExtent, &depth))
172*03ce13f7SAndroid Build Coastguard Worker 	{
173*03ce13f7SAndroid Build Coastguard Worker 		surfaceLost = true;
174*03ce13f7SAndroid Build Coastguard Worker 		return VK_ERROR_SURFACE_LOST_KHR;
175*03ce13f7SAndroid Build Coastguard Worker 	}
176*03ce13f7SAndroid Build Coastguard Worker 
177*03ce13f7SAndroid Build Coastguard Worker 	const VkExtent3D &extent = image->getImage()->getExtent();
178*03ce13f7SAndroid Build Coastguard Worker 
179*03ce13f7SAndroid Build Coastguard Worker 	if(windowExtent.width != extent.width || windowExtent.height != extent.height)
180*03ce13f7SAndroid Build Coastguard Worker 	{
181*03ce13f7SAndroid Build Coastguard Worker 		return VK_ERROR_OUT_OF_DATE_KHR;
182*03ce13f7SAndroid Build Coastguard Worker 	}
183*03ce13f7SAndroid Build Coastguard Worker 
184*03ce13f7SAndroid Build Coastguard Worker 	if(!mitSHM)
185*03ce13f7SAndroid Build Coastguard Worker 	{
186*03ce13f7SAndroid Build Coastguard Worker 		// TODO: Convert image if not RGB888.
187*03ce13f7SAndroid Build Coastguard Worker 		int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
188*03ce13f7SAndroid Build Coastguard Worker 		int bytesPerPixel = static_cast<int>(image->getImage()->getFormat(VK_IMAGE_ASPECT_COLOR_BIT).bytes());
189*03ce13f7SAndroid Build Coastguard Worker 		int width = stride / bytesPerPixel;
190*03ce13f7SAndroid Build Coastguard Worker 		auto buffer = reinterpret_cast<uint8_t *>(image->getImageMemory()->getOffsetPointer(0));
191*03ce13f7SAndroid Build Coastguard Worker 		size_t max_request_size = static_cast<size_t>(libXCB->xcb_get_maximum_request_length(connection)) * 4;
192*03ce13f7SAndroid Build Coastguard Worker 		size_t max_strides = (max_request_size - sizeof(xcb_put_image_request_t)) / stride;
193*03ce13f7SAndroid Build Coastguard Worker 		for(size_t y = 0; y < extent.height; y += max_strides)
194*03ce13f7SAndroid Build Coastguard Worker 		{
195*03ce13f7SAndroid Build Coastguard Worker 			size_t num_strides = std::min(max_strides, extent.height - y);
196*03ce13f7SAndroid Build Coastguard Worker 			libXCB->xcb_put_image(
197*03ce13f7SAndroid Build Coastguard Worker 			    connection,
198*03ce13f7SAndroid Build Coastguard Worker 			    XCB_IMAGE_FORMAT_Z_PIXMAP,
199*03ce13f7SAndroid Build Coastguard Worker 			    window,
200*03ce13f7SAndroid Build Coastguard Worker 			    gc,
201*03ce13f7SAndroid Build Coastguard Worker 			    width,
202*03ce13f7SAndroid Build Coastguard Worker 			    num_strides,
203*03ce13f7SAndroid Build Coastguard Worker 			    0, y,                  // dst x, y
204*03ce13f7SAndroid Build Coastguard Worker 			    0,                     // left_pad
205*03ce13f7SAndroid Build Coastguard Worker 			    depth,
206*03ce13f7SAndroid Build Coastguard Worker 			    num_strides * stride,  // data_len
207*03ce13f7SAndroid Build Coastguard Worker 			    buffer + y * stride    // data
208*03ce13f7SAndroid Build Coastguard Worker 			);
209*03ce13f7SAndroid Build Coastguard Worker 		}
210*03ce13f7SAndroid Build Coastguard Worker 		assert(libXCB->xcb_connection_has_error(connection) == 0);
211*03ce13f7SAndroid Build Coastguard Worker 	}
212*03ce13f7SAndroid Build Coastguard Worker 	else
213*03ce13f7SAndroid Build Coastguard Worker 	{
214*03ce13f7SAndroid Build Coastguard Worker 		auto it = pixmaps.find(image);
215*03ce13f7SAndroid Build Coastguard Worker 		assert(it != pixmaps.end());
216*03ce13f7SAndroid Build Coastguard Worker 		libXCB->xcb_copy_area(
217*03ce13f7SAndroid Build Coastguard Worker 		    connection,
218*03ce13f7SAndroid Build Coastguard Worker 		    it->second.pixmap,
219*03ce13f7SAndroid Build Coastguard Worker 		    window,
220*03ce13f7SAndroid Build Coastguard Worker 		    gc,
221*03ce13f7SAndroid Build Coastguard Worker 		    0, 0,  // src x, y
222*03ce13f7SAndroid Build Coastguard Worker 		    0, 0,  // dst x, y
223*03ce13f7SAndroid Build Coastguard Worker 		    extent.width,
224*03ce13f7SAndroid Build Coastguard Worker 		    extent.height);
225*03ce13f7SAndroid Build Coastguard Worker 	}
226*03ce13f7SAndroid Build Coastguard Worker 	libXCB->xcb_flush(connection);
227*03ce13f7SAndroid Build Coastguard Worker 
228*03ce13f7SAndroid Build Coastguard Worker 	return VK_SUCCESS;
229*03ce13f7SAndroid Build Coastguard Worker }
230*03ce13f7SAndroid Build Coastguard Worker 
231*03ce13f7SAndroid Build Coastguard Worker }  // namespace vk
232