diff --git a/driver/driver.c b/driver/driver.c index 7a7df38..906b345 100644 --- a/driver/driver.c +++ b/driver/driver.c @@ -95,6 +95,14 @@ typedef struct VkDevice_T int numQueues[numQueueFamilies]; } _device; +typedef struct VkSwapchain_T +{ + _image* images; + uint32_t numImages; + uint32_t backbufferIdx; + VkSurfaceKHR surface; +} _swapchain; + /* * https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkEnumerateInstanceExtensionProperties * When pLayerName parameter is NULL, only extensions provided by the Vulkan implementation or by implicitly enabled layers are returned. When pLayerName is the name of a layer, @@ -587,12 +595,12 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR( pSurfaceCapabilities->minImageCount = 1; //min 1 pSurfaceCapabilities->maxImageCount = 2; //TODO max 2 for double buffering for now... - pSurfaceCapabilities->currentExtent.width = ((modeset_dev*)surface)->bufs[0].width; - pSurfaceCapabilities->currentExtent.height = ((modeset_dev*)surface)->bufs[0].height; - pSurfaceCapabilities->minImageExtent.width = ((modeset_dev*)surface)->bufs[0].width; //TODO - pSurfaceCapabilities->minImageExtent.height = ((modeset_dev*)surface)->bufs[0].height; //TODO - pSurfaceCapabilities->maxImageExtent.width = ((modeset_dev*)surface)->bufs[0].width; //TODO - pSurfaceCapabilities->maxImageExtent.height = ((modeset_dev*)surface)->bufs[0].height; //TODO + pSurfaceCapabilities->currentExtent.width = ((modeset_dev*)surface)->width; + pSurfaceCapabilities->currentExtent.height = ((modeset_dev*)surface)->height; + pSurfaceCapabilities->minImageExtent.width = ((modeset_dev*)surface)->width; //TODO + pSurfaceCapabilities->minImageExtent.height = ((modeset_dev*)surface)->height; //TODO + pSurfaceCapabilities->maxImageExtent.width = ((modeset_dev*)surface)->width; //TODO + pSurfaceCapabilities->maxImageExtent.height = ((modeset_dev*)surface)->height; //TODO pSurfaceCapabilities->maxImageArrayLayers = 1; //TODO maybe more layers for cursor etc. pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; //TODO no rotation for now pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; //TODO get this from dev @@ -711,7 +719,43 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( //TODO: allocator is ignored for now assert(pAllocator == 0); - *pSwapchain = pCreateInfo->surface; //TODO + *pSwapchain = malloc(sizeof(_swapchain)); + if(!*pSwapchain) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + _swapchain* s = *pSwapchain; + + //TODO flags, layers, queue sharing, pretransform, composite alpha, present mode..., clipped, oldswapchain + //TODO external sync on surface, oldswapchain + + s->images = malloc(sizeof(_image) * pCreateInfo->minImageCount); + if(!s->images) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + s->backbufferIdx = 0; + s->numImages = pCreateInfo->minImageCount; + s->surface = pCreateInfo->surface; + + for(int c = 0; c < pCreateInfo->minImageCount; ++c) + { + //TODO image format, color space + //rest is filled out by create fb + s->images[c].width = pCreateInfo->imageExtent.width; + s->images[c].height = pCreateInfo->imageExtent.height; + s->images[c].depth = 1; + s->images[c].layers = 1; + s->images[c].miplevels = 1; + s->images[c].samples = 1; //TODO + s->images[c].usageBits = pCreateInfo->imageUsage; + + int res = modeset_create_fb(controlFd, &s->images[c]); assert(res == 0); + + res = modeset_fb_for_dev(controlFd, s->surface, &s->images[c]); assert(res == 0); + } return VK_SUCCESS; } @@ -735,26 +779,26 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR( assert(swapchain); assert(pSwapchainImageCount); - const int numImages = 2; + _swapchain* s = swapchain; if(!pSwapchainImages) { - *pSwapchainImageCount = numImages; + *pSwapchainImageCount = s->numImages; return VK_SUCCESS; } int arraySize = *pSwapchainImageCount; - int elementsWritten = min(numImages, arraySize); + int elementsWritten = min(s->numImages, arraySize); for(int c = 0; c < elementsWritten; ++c) { //TODO - pSwapchainImages[c] = c; + pSwapchainImages[c] = &s->images[c]; } *pSwapchainImageCount = elementsWritten; - if(elementsWritten < numImages) + if(elementsWritten < s->numImages) { return VK_INCOMPLETE; } @@ -993,7 +1037,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage( { assert(commandBuffer); - //TODO + //TODO implement VkImage to be able to clear backbuffer } /* @@ -1043,9 +1087,8 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( //TODO we need to keep track of currently acquired images? //TODO wait timeout? - VkSurfaceKHR surf = (VkSurfaceKHR)swapchain; - *pImageIndex = ((modeset_dev*)surf)->front_buf ^ 1; //return back buffer index + *pImageIndex = ((_swapchain*)swapchain)->backbufferIdx; //return back buffer index //signal semaphore int semVal; sem_getvalue((sem_t*)semaphore, &semVal); assert(semVal <= 0); //make sure semaphore is unsignalled @@ -1180,7 +1223,9 @@ VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR( for(int c = 0; c < pPresentInfo->swapchainCount; ++c) { - modeset_swapbuffer(controlFd, (modeset_dev*)pPresentInfo->pSwapchains[c], pPresentInfo->pImageIndices[c]); + _swapchain* s = pPresentInfo->pSwapchains[c]; + modeset_present_buffer(controlFd, (modeset_dev*)s->surface, &s->images[s->backbufferIdx]); + s->backbufferIdx = (s->backbufferIdx + 1) % s->numImages; } return VK_SUCCESS; @@ -1292,7 +1337,17 @@ VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR( //TODO: allocator is ignored for now assert(pAllocator == 0); - //TODO + //TODO flush all ops + + _swapchain* s = swapchain; + + for(int c = 0; c < s->numImages; ++c) + { + modeset_destroy_fb(controlFd, &s->images[c]); + } + + free(s->images); + free(s); } /* diff --git a/driver/modeset.c b/driver/modeset.c index 225bee4..a331801 100644 --- a/driver/modeset.c +++ b/driver/modeset.c @@ -51,8 +51,6 @@ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn, struct modeset_dev *dev); -static int modeset_create_fb(int fd, struct modeset_buf *buf); -static void modeset_destroy_fb(int fd, struct modeset_buf *buf); static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn, struct modeset_dev *dev); @@ -138,19 +136,25 @@ modeset_dev* modeset_create(int fd) // free resources again drmModeFreeResources(res); + return ret_dev; +} + +int modeset_fb_for_dev(int fd, modeset_dev* dev, _image* buffer) +{ + int ret; + struct modeset_dev *iter; - struct modeset_buf *buf; - for (iter = ret_dev; iter; iter = iter->next) { + //struct modeset_buf *buf; + for (iter = dev; iter; iter = iter->next) { iter->saved_crtc = drmModeGetCrtc(fd, iter->crtc); - buf = &iter->bufs[iter->front_buf]; - ret = drmModeSetCrtc(fd, iter->crtc, buf->fb, 0, 0, + ret = drmModeSetCrtc(fd, iter->crtc, buffer->fb, 0, 0, &iter->conn, 1, &iter->mode); if (ret) printf("cannot set CRTC for connector %u (%d): %m\n", iter->conn, errno); } - return ret_dev; + return 0; } /* @@ -182,12 +186,10 @@ static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn, // copy the mode information into our device structure and into both buffers memcpy(&dev->mode, &conn->modes[0], sizeof(dev->mode)); - dev->bufs[0].width = conn->modes[0].hdisplay; - dev->bufs[0].height = conn->modes[0].vdisplay; - dev->bufs[1].width = conn->modes[0].hdisplay; - dev->bufs[1].height = conn->modes[0].vdisplay; + dev->width = conn->modes[0].hdisplay; + dev->height = conn->modes[0].vdisplay; printf("mode for connector %u is %ux%u\n", - conn->connector_id, dev->bufs[0].width, dev->bufs[0].height); + conn->connector_id, dev->width, dev->height); // find a crtc for this connector ret = modeset_find_crtc(fd, res, conn, dev); @@ -197,6 +199,14 @@ static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn, return ret; } + return 0; +} + + +/*static int modeset_create_swapchain(int fd, drmModeConnector *conn, struct modeset_dev *dev) +{ + int ret; + // create framebuffer #1 for this CRTC ret = modeset_create_fb(fd, &dev->bufs[0]); if (ret) { @@ -215,7 +225,7 @@ static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn, } return 0; -} +}*/ /* * modeset_find_crtc() stays the same. @@ -305,7 +315,7 @@ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn, * modeset_setup_dev() so we can use them here. */ -static int modeset_create_fb(int fd, struct modeset_buf *buf) +int modeset_create_fb(int fd, _image *buf) { struct drm_mode_create_dumb creq; struct drm_mode_destroy_dumb dreq; @@ -341,6 +351,7 @@ static int modeset_create_fb(int fd, struct modeset_buf *buf) return ret; } + /** // prepare buffer for memory mapping memset(&mreq, 0, sizeof(mreq)); mreq.handle = buf->handle; @@ -374,6 +385,7 @@ static int modeset_create_fb(int fd, struct modeset_buf *buf) // clear the framebuffer to 0 memset(buf->map, 0, buf->size); + /**/ return 0; } @@ -385,12 +397,12 @@ static int modeset_create_fb(int fd, struct modeset_buf *buf) * We simply unmap the buffer, remove the drm-FB and destroy the memory buffer. */ -static void modeset_destroy_fb(int fd, struct modeset_buf *buf) +void modeset_destroy_fb(int fd, _image* buf) { struct drm_mode_destroy_dumb dreq; // unmap buffer - munmap(buf->map, buf->size); + //munmap(buf->map, buf->size); // delete framebuffer drmModeRmFB(fd, buf->fb); @@ -435,24 +447,25 @@ static void modeset_destroy_fb(int fd, struct modeset_buf *buf) * vertical-sync. */ -void modeset_swapbuffer(int fd, modeset_dev* dev, unsigned index) +void modeset_present_buffer(int fd, modeset_dev* dev, _image* buffer) { //TODO use index!! struct modeset_dev *iter; - struct modeset_buf *buf; + //struct modeset_buf *buf; int ret; - for (iter = dev; iter; iter = iter->next) { - buf = &iter->bufs[iter->front_buf ^ 1]; + for (iter = dev; iter; iter = iter->next) + { + //buf = &iter->bufs[iter->front_buf ^ 1]; - ret = drmModeSetCrtc(fd, iter->crtc, buf->fb, 0, 0, + ret = drmModeSetCrtc(fd, iter->crtc, buffer->fb, 0, 0, &iter->conn, 1, &iter->mode); if (ret) printf("cannot flip CRTC for connector %u (%d): %m\n", iter->conn, errno); - else - iter->front_buf ^= 1; + //else + // iter->front_buf ^= 1; } } @@ -482,8 +495,8 @@ void modeset_destroy(int fd, modeset_dev* dev) drmModeFreeCrtc(iter->saved_crtc); // destroy framebuffers - modeset_destroy_fb(fd, &iter->bufs[1]); - modeset_destroy_fb(fd, &iter->bufs[0]); + //modeset_destroy_fb(fd, &iter->bufs[1]); + //modeset_destroy_fb(fd, &iter->bufs[0]); // free allocated memory free(iter); diff --git a/driver/modeset.h b/driver/modeset.h index 65c24a1..cbfe71e 100644 --- a/driver/modeset.h +++ b/driver/modeset.h @@ -17,31 +17,35 @@ extern "C" { #include #include -typedef struct modeset_buf { - uint32_t width; - uint32_t height; - uint32_t stride; - uint32_t size; +typedef struct VkImage_T +{ uint32_t handle; - uint8_t *map; - uint32_t fb; -} modeset_buf; + uint32_t fb; //needed for swapchain + uint32_t width, height, depth; + uint32_t miplevels, layers, samples, size, stride; + uint32_t usageBits; +} _image; typedef struct modeset_dev { struct modeset_dev *next; - unsigned int front_buf; - struct modeset_buf bufs[2]; + //unsigned int front_buf; + //struct modeset_buf bufs[2]; drmModeModeInfo mode; uint32_t conn; uint32_t crtc; drmModeCrtc *saved_crtc; + uint32_t width; + uint32_t height; } modeset_dev; modeset_dev* modeset_create(int fd); -void modeset_swapbuffer(int fd, modeset_dev* dev, unsigned index); +void modeset_present_buffer(int fd, modeset_dev* dev, _image* buffer); void modeset_destroy(int fd, modeset_dev* dev); +int modeset_create_fb(int fd, _image *buf); +void modeset_destroy_fb(int fd, _image *buf); +int modeset_fb_for_dev(int fd, modeset_dev* dev, _image* buffer); #if defined (__cplusplus) }