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