mirror of
https://github.com/Yours3lf/rpi-vk-driver.git
synced 2025-02-19 16:54:18 +01:00
rewriting modesetting so that direct to display is supported
This commit is contained in:
parent
db4d3d6507
commit
a67cf48094
@ -515,6 +515,12 @@ typedef struct VkQueryPool_T
|
||||
_query* queryPool;
|
||||
} _queryPool;
|
||||
|
||||
typedef struct VkDisplayModeKHR_T
|
||||
{
|
||||
uint32_t connectorID;
|
||||
uint32_t modeID;
|
||||
} _displayMode;
|
||||
|
||||
uint32_t getFormatBpp(VkFormat f);
|
||||
uint32_t packVec4IntoABGR8(const float rgba[4]);
|
||||
void createImageBO(_image* i);
|
||||
|
@ -1020,6 +1020,24 @@ VKAPI_ATTR VkResult VKAPI_CALL rpi_vkAcquireProfilingLockKHR(
|
||||
VKAPI_ATTR void VKAPI_CALL rpi_vkReleaseProfilingLockKHR(
|
||||
VkDevice device);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkGetPhysicalDeviceDisplayPropertiesKHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
uint32_t* pPropertyCount,
|
||||
VkDisplayPropertiesKHR* pProperties);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkGetDisplayModePropertiesKHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkDisplayKHR display,
|
||||
uint32_t* pPropertyCount,
|
||||
VkDisplayModePropertiesKHR* pProperties);
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkCreateDisplayModeKHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkDisplayKHR display,
|
||||
const VkDisplayModeCreateInfoKHR* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDisplayModeKHR* pMode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -37,9 +37,6 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInsta
|
||||
{
|
||||
void* ptr = 0;
|
||||
|
||||
if(!strcmp(pName, "vkCreateRpiSurfaceEXT"))
|
||||
ptr = &rpi_vkCreateRpiSurfaceEXT;
|
||||
|
||||
if(!strcmp(pName, "vkCreateShaderModuleFromRpiAssemblyEXT"))
|
||||
ptr = &rpi_vkCreateShaderModuleFromRpiAssemblyEXT;
|
||||
|
||||
@ -475,6 +472,10 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL rpi_vkGetInstanceProcAddr(
|
||||
RETFUNC(vkAcquireProfilingLockKHR);
|
||||
RETFUNC(vkReleaseProfilingLockKHR);
|
||||
|
||||
RETFUNC(vkGetPhysicalDeviceDisplayPropertiesKHR);
|
||||
RETFUNC(vkGetDisplayModePropertiesKHR);
|
||||
RETFUNC(vkCreateDisplayModeKHR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
316
driver/modeset.c
316
driver/modeset.c
@ -1,54 +1,5 @@
|
||||
/*
|
||||
* modeset - DRM Double-Buffered Modesetting Example
|
||||
*
|
||||
* Written 2012 by David Herrmann <dh.herrmann@googlemail.com>
|
||||
* Dedicated to the Public Domain.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DRM Modesetting Howto
|
||||
* This document describes the DRM modesetting API. Before we can use the DRM
|
||||
* API, we have to include xf86drm.h and xf86drmMode.h. Both are provided by
|
||||
* libdrm which every major distribution ships by default. It has no other
|
||||
* dependencies and is pretty small.
|
||||
*
|
||||
* Please ignore all forward-declarations of functions which are used later. I
|
||||
* reordered the functions so you can read this document from top to bottom. If
|
||||
* you reimplement it, you would probably reorder the functions to avoid all the
|
||||
* nasty forward declarations.
|
||||
*
|
||||
* For easier reading, we ignore all memory-allocation errors of malloc() and
|
||||
* friends here. However, we try to correctly handle all other kinds of errors
|
||||
* that may occur.
|
||||
*
|
||||
* All functions and global variables are prefixed with "modeset_*" in this
|
||||
* file. So it should be clear whether a function is a local helper or if it is
|
||||
* provided by some external library.
|
||||
*/
|
||||
|
||||
#include "modeset.h"
|
||||
|
||||
/*
|
||||
* Previously, we used the modeset_dev objects to hold buffer informations, too.
|
||||
* Technically, we could have split them but avoided this to make the
|
||||
* example simpler.
|
||||
* However, in this example we need 2 buffers. One back buffer and one front
|
||||
* buffer. So we introduce a new structure modeset_buf which contains everything
|
||||
* related to a single buffer. Each device now gets an array of two of these
|
||||
* buffers.
|
||||
* Each buffer consists of width, height, stride, size, handle, map and fb-id.
|
||||
* They have the same meaning as before.
|
||||
*
|
||||
* Each device also gets a new integer field: front_buf. This field contains the
|
||||
* index of the buffer that is currently used as front buffer / scanout buffer.
|
||||
* In our example it can be 0 or 1. We flip it by using XOR:
|
||||
* dev->front_buf ^= dev->front_buf
|
||||
*
|
||||
* Everything else stays the same.
|
||||
*/
|
||||
|
||||
//static struct modeset_dev *modeset_list = NULL;
|
||||
|
||||
static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
|
||||
struct modeset_dev *dev);
|
||||
static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn,
|
||||
@ -88,13 +39,6 @@ modeset_dev* modeset_create(int fd)
|
||||
struct modeset_dev *dev;
|
||||
int ret;
|
||||
|
||||
//we'll use a buffer created by the vc4 kernel module instead
|
||||
/*uint64_t has_dumb;
|
||||
if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || !has_dumb) {
|
||||
printf("drm device does not support dumb buffers\n");
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
// retrieve resources
|
||||
res = drmModeGetResources(fd);
|
||||
if (!res) {
|
||||
@ -204,30 +148,6 @@ static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn,
|
||||
}
|
||||
|
||||
|
||||
/*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) {
|
||||
printf("cannot create framebuffer for connector %u\n",
|
||||
conn->connector_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// create framebuffer #2 for this CRTC
|
||||
ret = modeset_create_fb(fd, &dev->bufs[1]);
|
||||
if (ret) {
|
||||
printf("cannot create framebuffer for connector %u\n",
|
||||
conn->connector_id);
|
||||
modeset_destroy_fb(fd, &dev->bufs[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
/*
|
||||
* modeset_find_crtc() stays the same.
|
||||
*/
|
||||
@ -318,27 +238,8 @@ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
|
||||
|
||||
int modeset_create_fb(int fd, _image *buf)
|
||||
{
|
||||
//struct drm_mode_create_dumb creq;
|
||||
//struct drm_mode_destroy_dumb dreq;
|
||||
//struct drm_mode_map_dumb mreq;
|
||||
int ret;
|
||||
|
||||
//we'll use a buffer created by vc4 instead
|
||||
// create dumb buffer
|
||||
/*memset(&creq, 0, sizeof(creq));
|
||||
creq.width = buf->width;
|
||||
creq.height = buf->height;
|
||||
creq.bpp = 32;
|
||||
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
|
||||
if (ret < 0) {
|
||||
printf("cannot create dumb buffer (%d): %m\n",
|
||||
errno);
|
||||
return -errno;
|
||||
}
|
||||
buf->stride = creq.pitch;
|
||||
buf->size = creq.size;
|
||||
buf->handle = creq.handle;*/
|
||||
|
||||
// create framebuffer object for the dumb-buffer
|
||||
ret = drmModeAddFB(fd, buf->width, buf->height, 24, 32, buf->stride,
|
||||
buf->boundMem->bo, &buf->fb);
|
||||
@ -347,48 +248,9 @@ int modeset_create_fb(int fd, _image *buf)
|
||||
errno);
|
||||
ret = -errno;
|
||||
|
||||
//memset(&dreq, 0, sizeof(dreq));
|
||||
//dreq.handle = buf->handle;
|
||||
//drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
// prepare buffer for memory mapping
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.handle = buf->handle;
|
||||
ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
|
||||
if (ret) {
|
||||
printf("cannot map dumb buffer (%d): %m\n",
|
||||
errno);
|
||||
ret = -errno;
|
||||
|
||||
drmModeRmFB(fd, buf->fb);
|
||||
memset(&dreq, 0, sizeof(dreq));
|
||||
dreq.handle = buf->handle;
|
||||
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// perform actual memory mapping
|
||||
buf->map = mmap(0, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
fd, mreq.offset);
|
||||
if (buf->map == MAP_FAILED) {
|
||||
printf("cannot mmap dumb buffer (%d): %m\n",
|
||||
errno);
|
||||
ret = -errno;
|
||||
|
||||
drmModeRmFB(fd, buf->fb);
|
||||
memset(&dreq, 0, sizeof(dreq));
|
||||
dreq.handle = buf->handle;
|
||||
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// clear the framebuffer to 0
|
||||
memset(buf->map, 0, buf->size);
|
||||
/**/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -401,54 +263,10 @@ int modeset_create_fb(int fd, _image *buf)
|
||||
|
||||
void modeset_destroy_fb(int fd, _image* buf)
|
||||
{
|
||||
//struct drm_mode_destroy_dumb dreq;
|
||||
|
||||
// unmap buffer
|
||||
//munmap(buf->map, buf->size);
|
||||
|
||||
// delete framebuffer
|
||||
drmModeRmFB(fd, buf->fb);
|
||||
|
||||
// delete dumb buffer
|
||||
/*memset(&dreq, 0, sizeof(dreq));
|
||||
dreq.handle = buf->handle;
|
||||
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);*/
|
||||
}
|
||||
|
||||
/*
|
||||
* modeset_draw() is the place where things change. The render-logic is the same
|
||||
* and we still draw a solid-color on the whole screen. However, we now have two
|
||||
* buffers and need to flip between them.
|
||||
*
|
||||
* So before drawing into a framebuffer, we need to find the back-buffer.
|
||||
* Remember, dev->font_buf is the index of the front buffer, so
|
||||
* dev->front_buf ^ 1 is the index of the back buffer. We simply use
|
||||
* dev->bufs[dev->front_buf ^ 1] to get the back-buffer and draw into it.
|
||||
*
|
||||
* After we finished drawing, we need to flip the buffers. We do this with the
|
||||
* same call as we initially set the CRTC: drmModeSetCrtc(). However, we now
|
||||
* pass the back-buffer as new framebuffer as we want to flip them.
|
||||
* The only thing left to do is to change the dev->front_buf index to point to
|
||||
* the new back-buffer (which was previously the front buffer).
|
||||
* We then sleep for a short time period and start drawing again.
|
||||
*
|
||||
* If you run this example, you will notice that there is almost no flickering,
|
||||
* anymore. The buffers are now swapped as a whole so each new frame shows
|
||||
* always the whole new image. If you look carefully, you will notice that the
|
||||
* modeset.c example showed many screen corruptions during redraw-cycles.
|
||||
*
|
||||
* However, this example is still not perfect. Imagine the display-controller is
|
||||
* currently scanning out a new image and we call drmModeSetCrtc()
|
||||
* simultaneously. It will then have the same effect as if we used a single
|
||||
* buffer and we get some tearing. But, the chance that this happens is a lot
|
||||
* less likely as with a single-buffer. This is because there is a long period
|
||||
* between each frame called vertical-blank where the display-controller does
|
||||
* not perform a scanout. If we swap the buffers in this period, we have the
|
||||
* guarantee that there will be no tearing. See the modeset-vsync.c example if
|
||||
* you want to know how you can guarantee that the swap takes place at a
|
||||
* vertical-sync.
|
||||
*/
|
||||
|
||||
void modeset_present_buffer(int fd, modeset_dev* dev, _image* buffer)
|
||||
{
|
||||
//TODO use index!!
|
||||
@ -459,20 +277,15 @@ void modeset_present_buffer(int fd, modeset_dev* dev, _image* buffer)
|
||||
}
|
||||
|
||||
struct modeset_dev *iter;
|
||||
//struct modeset_buf *buf;
|
||||
int ret;
|
||||
|
||||
for (iter = dev; iter; iter = iter->next)
|
||||
{
|
||||
//buf = &iter->bufs[iter->front_buf ^ 1];
|
||||
|
||||
ret = drmModeSetCrtc(fd, iter->crtc, buffer->fb, 0, 0,
|
||||
&iter->conn, 1, &iter->mode);
|
||||
if (ret)
|
||||
fprintf(stderr, "cannot flip CRTC for connector %u (%d): %m\n",
|
||||
iter->conn, errno);
|
||||
//else
|
||||
// iter->front_buf ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -501,36 +314,109 @@ void modeset_destroy(int fd, modeset_dev* dev)
|
||||
&iter->saved_crtc->mode);
|
||||
drmModeFreeCrtc(iter->saved_crtc);
|
||||
|
||||
// destroy framebuffers
|
||||
//modeset_destroy_fb(fd, &iter->bufs[1]);
|
||||
//modeset_destroy_fb(fd, &iter->bufs[0]);
|
||||
|
||||
// free allocated memory
|
||||
free(iter);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This was a very short extension to the basic modesetting example that shows
|
||||
* how double-buffering is implemented. Double-buffering is the de-facto
|
||||
* standard in any graphics application so any other example will be based on
|
||||
* this. It is important to understand the ideas behind it as the code is pretty
|
||||
* easy and short compared to modeset.c.
|
||||
*
|
||||
* Double-buffering doesn't solve all problems. Vsync'ed page-flips solve most
|
||||
* of the problems that still occur, but has problems on it's own (see
|
||||
* modeset-vsync.c for a discussion).
|
||||
*
|
||||
* If you want more code, I can recommend reading the source-code of:
|
||||
* - plymouth (which uses dumb-buffers like this example; very easy to understand)
|
||||
* - kmscon (which uses libuterm to do this)
|
||||
* - wayland (very sophisticated DRM renderer; hard to understand fully as it
|
||||
* uses more complicated techniques like DRM planes)
|
||||
* - xserver (very hard to understand as it is split across many files/projects)
|
||||
*
|
||||
* Any feedback is welcome. Feel free to use this code freely for your own
|
||||
* documentation or projects.
|
||||
*
|
||||
* - Hosted on http://github.com/dvdhrm/docs
|
||||
* - Written by David Herrmann <dh.herrmann@googlemail.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
void modeset_enum_displays(int fd, uint32_t* numDisplays, modeset_display** displays)
|
||||
{
|
||||
drmModeResPtr resPtr = drmModeGetResources(fd);
|
||||
|
||||
uint32_t tmpNumDisplays = 0;
|
||||
modeset_display tmpDisplays[16];
|
||||
|
||||
for(uint32_t c = 0; c < resPtr->count_connectors; ++c)
|
||||
{
|
||||
drmModeConnectorPtr connPtr = drmModeGetConnector(fd, resPtr->connectors[c]);
|
||||
|
||||
if(connPtr->connection != DRM_MODE_CONNECTED)
|
||||
{
|
||||
continue; //skip unused connector
|
||||
}
|
||||
|
||||
if(!connPtr->count_modes)
|
||||
{
|
||||
continue; //skip connectors with no valid modes
|
||||
}
|
||||
|
||||
memcpy(tmpDisplays[tmpNumDisplays].name, connPtr->modes[0].name, 32);
|
||||
|
||||
tmpDisplays[tmpNumDisplays].mmWidth = connPtr->mmWidth;
|
||||
tmpDisplays[tmpNumDisplays].mmHeight = connPtr->mmHeight;
|
||||
tmpDisplays[tmpNumDisplays].resWidth = connPtr->modes[0].hdisplay;
|
||||
tmpDisplays[tmpNumDisplays].resHeight = connPtr->modes[0].vdisplay;
|
||||
tmpDisplays[tmpNumDisplays].connectorID = connPtr->connector_id;
|
||||
|
||||
tmpNumDisplays++;
|
||||
|
||||
assert(tmpNumDisplays < 16);
|
||||
|
||||
drmModeFreeConnector(connPtr);
|
||||
}
|
||||
|
||||
drmModeFreeResources(resPtr);
|
||||
|
||||
*numDisplays = tmpNumDisplays;
|
||||
|
||||
memcpy(*displays, tmpDisplays, tmpNumDisplays * sizeof(modeset_display));
|
||||
}
|
||||
|
||||
void modeset_enum_modes_for_display(int fd, uint32_t display, uint32_t* numModes, modeset_display_mode** modes)
|
||||
{
|
||||
drmModeResPtr resPtr = drmModeGetResources(fd);
|
||||
|
||||
drmModeConnectorPtr connPtr = drmModeGetConnector(fd, display);
|
||||
|
||||
uint32_t tmpNumModes = 0;
|
||||
modeset_display_mode tmpModes[1024];
|
||||
|
||||
for(uint32_t c = 0; c < connPtr->count_modes; ++c)
|
||||
{
|
||||
tmpModes[tmpNumModes].connectorID = display;
|
||||
tmpModes[tmpNumModes].modeID = c;
|
||||
tmpModes[tmpNumModes].refreshRate = connPtr->modes[c].vrefresh;
|
||||
tmpModes[tmpNumModes].resWidth = connPtr->modes[c].hdisplay;
|
||||
tmpModes[tmpNumModes].resHeight = connPtr->modes[c].vdisplay;
|
||||
|
||||
tmpNumModes++;
|
||||
|
||||
assert(tmpNumModes < 1024);
|
||||
}
|
||||
|
||||
drmModeFreeConnector(connPtr);
|
||||
drmModeFreeResources(resPtr);
|
||||
|
||||
*numModes = tmpNumModes;
|
||||
memcpy(*modes, tmpModes, tmpNumModes * sizeof(modeset_display_mode));
|
||||
}
|
||||
|
||||
void modeset_create_surface_for_mode(int fd, uint32_t display, uint32_t mode, modeset_display_surface* surface)
|
||||
{
|
||||
drmModeResPtr resPtr = drmModeGetResources(fd);
|
||||
|
||||
drmModeConnectorPtr connPtr = drmModeGetConnector(fd, display);
|
||||
|
||||
drmModeEncoderPtr encPtr = 0;
|
||||
|
||||
//if current encoder is valid, try to use that
|
||||
if(connPtr->encoder_id)
|
||||
{
|
||||
encPtr = drmModeGetEncoder(fd, connPtr->encoder_id);
|
||||
}
|
||||
|
||||
if(encPtr)
|
||||
{
|
||||
if(encPtr->crtc_id)
|
||||
{
|
||||
surface->connectorID = display;
|
||||
surface->modeID = mode;
|
||||
surface->encoderID = connPtr->encoder_id;
|
||||
surface->crtcID = encPtr->crtc_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,6 @@ extern "C" {
|
||||
typedef struct modeset_dev {
|
||||
struct modeset_dev *next;
|
||||
|
||||
//unsigned int front_buf;
|
||||
//struct modeset_buf bufs[2];
|
||||
|
||||
drmModeModeInfo mode;
|
||||
uint32_t conn;
|
||||
uint32_t crtc;
|
||||
@ -35,6 +32,27 @@ typedef struct modeset_dev {
|
||||
uint32_t handle;
|
||||
} modeset_dev;
|
||||
|
||||
typedef struct modeset_display {
|
||||
char name[32];
|
||||
uint32_t mmWidth, mmHeight;
|
||||
uint32_t resWidth, resHeight;
|
||||
uint32_t connectorID;
|
||||
} modeset_display;
|
||||
|
||||
typedef struct modeset_display_mode {
|
||||
uint32_t connectorID;
|
||||
uint32_t modeID;
|
||||
uint32_t resWidth, resHeight;
|
||||
uint32_t refreshRate;
|
||||
} modeset_display_mode;
|
||||
|
||||
typedef struct modeset_display_surface {
|
||||
uint32_t connectorID;
|
||||
uint32_t modeID;
|
||||
uint32_t encoderID;
|
||||
uint32_t crtcID;
|
||||
} modeset_display_mode;
|
||||
|
||||
modeset_dev* modeset_create(int fd);
|
||||
void modeset_present_buffer(int fd, modeset_dev* dev, _image* buffer);
|
||||
void modeset_destroy(int fd, modeset_dev* dev);
|
||||
@ -42,6 +60,10 @@ 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);
|
||||
|
||||
void modeset_enum_displays(int fd, uint32_t* numDisplays, modeset_display** displays);
|
||||
void modeset_enum_modes_for_display(int fd, uint32_t display, uint32_t* numModes, modeset_display_mode** modes);
|
||||
void modeset_create_surface_for_mode(int fd, uint32_t display, uint32_t mode, modeset_display_surface* surface);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
@ -215,10 +215,6 @@ static VkExtensionProperties instanceExtensions[] =
|
||||
.extensionName = "VK_KHR_display",
|
||||
.specVersion = 21
|
||||
},
|
||||
{
|
||||
.extensionName = "VK_EXT_direct_mode_display",
|
||||
.specVersion = 1
|
||||
},
|
||||
{
|
||||
.extensionName = "VK_EXT_debug_report",
|
||||
.specVersion = 9
|
||||
@ -226,12 +222,7 @@ static VkExtensionProperties instanceExtensions[] =
|
||||
{
|
||||
.extensionName = "VK_EXT_debug_utils",
|
||||
.specVersion = 1
|
||||
},
|
||||
//TODO not an official extension, so can't expose it
|
||||
//{
|
||||
// .extensionName = "VK_KHR_rpi_surface",
|
||||
// .specVersion = 1
|
||||
//}
|
||||
}
|
||||
};
|
||||
#define numInstanceExtensions (sizeof(instanceExtensions) / sizeof(VkExtensionProperties))
|
||||
|
||||
|
@ -7,8 +7,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef VkResult (*PFN_vkCreateRpiSurfaceEXT)(
|
||||
VkPhysicalDevice physicalDevice);
|
||||
typedef VkResult (*PFN_vkCreateShaderModuleFromRpiAssemblyEXT)(
|
||||
VkPhysicalDevice physicalDevice);
|
||||
|
||||
@ -65,11 +63,6 @@ typedef struct LoaderTrampoline
|
||||
*
|
||||
*/
|
||||
|
||||
typedef enum VkRpiSurfaceCreateFlagsEXT {
|
||||
//reserved
|
||||
VK_RPI_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkRpiSurfaceCreateFlagsEXT;
|
||||
|
||||
|
||||
typedef enum VkRpiAssemblyMappingTypeEXT {
|
||||
VK_RPI_ASSEMBLY_MAPPING_TYPE_DESCRIPTOR = 0,
|
||||
@ -88,18 +81,6 @@ typedef struct VkRpiAssemblyMappingEXT {
|
||||
VkShaderStageFlagBits shaderStage;
|
||||
} VkRpiAssemblyMappingEXT;
|
||||
|
||||
//we need something like the other platforms to create surfaces on the RPI
|
||||
//so I created this little "extension"
|
||||
//full spec in this file ;)
|
||||
|
||||
typedef struct VkRpiSurfaceCreateInfoEXT {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkRpiSurfaceCreateFlagsEXT flags; //reserved
|
||||
const VkAllocationCallbacks* pAllocator;
|
||||
VkSurfaceKHR* pSurface;
|
||||
} VkRpiSurfaceCreateInfoEXT;
|
||||
|
||||
typedef struct VkRpiShaderModuleAssemblyCreateInfoEXT {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
|
@ -9,24 +9,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Implementation of our RPI specific "extension"
|
||||
*/
|
||||
VkResult rpi_vkCreateRpiSurfaceEXT(VkPhysicalDevice physicalDevice)
|
||||
{
|
||||
assert(physicalDevice);
|
||||
|
||||
//TODO use allocator!
|
||||
|
||||
_physicalDevice* ptr = physicalDevice;
|
||||
VkRpiSurfaceCreateInfoEXT* ci = ptr->customData;
|
||||
VkSurfaceKHR surfRes = (VkSurfaceKHR)modeset_create(controlFd);
|
||||
|
||||
*ci->pSurface = surfRes;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
//TODO collect shader performance data
|
||||
//eg number of texture samples etc.
|
||||
//TODO check if shader has flow control and make sure instance also has flow control
|
||||
|
@ -6,11 +6,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//extension name something like: VK_KHR_rpi_surface
|
||||
//extension that allows developers to create a surface to render to on Raspbian Stretch Lite
|
||||
extern VkResult rpi_vkCreateRpiSurfaceEXT(
|
||||
VkPhysicalDevice physicalDevice);
|
||||
|
||||
//extension that allows developers to submit QPU assembly directly and thus hand optimise code
|
||||
extern VkResult rpi_vkCreateShaderModuleFromRpiAssemblyEXT(
|
||||
VkPhysicalDevice physicalDevice);
|
||||
|
128
driver/wsi.c
128
driver/wsi.c
@ -9,13 +9,133 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkGetPhysicalDeviceDisplayPropertiesKHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
uint32_t* pPropertyCount,
|
||||
VkDisplayPropertiesKHR* pProperties)
|
||||
{
|
||||
assert(physicalDevice);
|
||||
assert(pPropertyCount);
|
||||
|
||||
uint32_t numDisplays;
|
||||
modeset_display displays[16];
|
||||
modeset_enum_displays(controlFd, &numDisplays, &displays);
|
||||
|
||||
if(!pProperties)
|
||||
{
|
||||
*pPropertyCount = numDisplays;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
int arraySize = *pPropertyCount;
|
||||
int elementsWritten = min(numDisplays, arraySize);
|
||||
|
||||
for(int c = 0; c < elementsWritten; ++c)
|
||||
{
|
||||
pProperties[c].display = displays[c].connectorID;
|
||||
char* name = (char*)malloc(32);
|
||||
memcpy(name, displays[c].name, 32);
|
||||
pProperties[c].displayName = (const char*)name;
|
||||
pProperties[c].physicalDimensions.width = displays[c].mmWidth;
|
||||
pProperties[c].physicalDimensions.height = displays[c].mmHeight;
|
||||
pProperties[c].physicalResolution.width = displays[c].resWidth;
|
||||
pProperties[c].physicalResolution.height = displays[c].resHeight;
|
||||
}
|
||||
|
||||
*pPropertyCount = elementsWritten;
|
||||
|
||||
if(arraySize < numDisplays)
|
||||
{
|
||||
return VK_INCOMPLETE;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkGetDisplayModePropertiesKHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkDisplayKHR display,
|
||||
uint32_t* pPropertyCount,
|
||||
VkDisplayModePropertiesKHR* pProperties)
|
||||
{
|
||||
assert(physicalDevice);
|
||||
assert(display);
|
||||
assert(pPropertyCount);
|
||||
|
||||
uint32_t numModes;
|
||||
modeset_display_mode modes[1024];
|
||||
modeset_enum_modes_for_display(controlFd, display, &numModes, &modes);
|
||||
|
||||
if(!pProperties)
|
||||
{
|
||||
*pPropertyCount = numModes;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
int arraySize = *pPropertyCount;
|
||||
int elementsWritten = min(numModes, arraySize);
|
||||
|
||||
for(int c = 0; c < elementsWritten; ++c)
|
||||
{
|
||||
_displayMode mode = { modes[c].connectorID, modes[c].modeID };
|
||||
memcpy(&pProperties[c].displayMode, &mode, sizeof(_displayMode));
|
||||
pProperties[c].parameters.visibleRegion.width = modes[c].resWidth;
|
||||
pProperties[c].parameters.visibleRegion.height = modes[c].resHeight;
|
||||
pProperties[c].parameters.refreshRate = modes[c].refreshRate;
|
||||
}
|
||||
|
||||
*pPropertyCount = elementsWritten;
|
||||
|
||||
if(arraySize < numModes)
|
||||
{
|
||||
return VK_INCOMPLETE;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkCreateDisplayModeKHR(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkDisplayKHR display,
|
||||
const VkDisplayModeCreateInfoKHR* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDisplayModeKHR* pMode)
|
||||
{
|
||||
assert(physicalDevice);
|
||||
assert(display);
|
||||
|
||||
uint32_t numModes;
|
||||
modeset_display_mode modes[1024];
|
||||
modeset_enum_modes_for_display(controlFd, display, &numModes, &modes);
|
||||
|
||||
for(uint32_t c = 0; c < numModes; ++c)
|
||||
{
|
||||
if(modes[c].refreshRate == pCreateInfo->parameters.refreshRate &&
|
||||
modes[c].resWidth == pCreateInfo->parameters.visibleRegion.width &&
|
||||
modes[c].resHeight == pCreateInfo->parameters.visibleRegion.height)
|
||||
{
|
||||
_displayMode mode = { modes[c].connectorID, modes[c].modeID };
|
||||
|
||||
memcpy(pMode, &mode, sizeof(_displayMode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkCreateDisplayPlaneSurfaceKHR(
|
||||
VkInstance instance,
|
||||
const VkDisplaySurfaceCreateInfoKHR* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkSurfaceKHR* pSurface)
|
||||
{
|
||||
fprintf(stderr, "vkCreateDisplayPlaneSurfaceKHR\n");
|
||||
assert(instance);
|
||||
assert(pSurface);
|
||||
|
||||
_displayMode mode = pCreateInfo->displayMode;
|
||||
|
||||
modeset_display_surface* surface = ALLOCATE(sizeof(modeset_display_surface), 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
|
||||
modeset_create_surface_for_mode(controlFd, mode.connectorID, mode.modeID, surface);
|
||||
|
||||
*pSurface = surface;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -31,12 +151,12 @@ VKAPI_ATTR void VKAPI_CALL rpi_vkDestroySurfaceKHR(
|
||||
{
|
||||
assert(instance);
|
||||
|
||||
//TODO use allocator
|
||||
|
||||
if(surface)
|
||||
{
|
||||
modeset_destroy(controlFd, (modeset_dev*)surface);
|
||||
//modeset_destroy(controlFd, (modeset_dev*)surface);
|
||||
}
|
||||
|
||||
FREE(surface);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -212,11 +212,11 @@ void createInstance() {
|
||||
}
|
||||
|
||||
void createWindowSurface() {
|
||||
PFN_vkCreateRpiSurfaceEXT vkCreateRpiSurfaceEXT = 0;
|
||||
vkCreateRpiSurfaceEXT = (PFN_vkCreateRpiSurfaceEXT)vkGetInstanceProcAddr(instance, "vkCreateRpiSurfaceEXT");
|
||||
|
||||
windowSurface = 0;
|
||||
|
||||
/*PFN_vkCreateRpiSurfaceEXT vkCreateRpiSurfaceEXT = 0;
|
||||
vkCreateRpiSurfaceEXT = (PFN_vkCreateRpiSurfaceEXT)vkGetInstanceProcAddr(instance, "vkCreateRpiSurfaceEXT");
|
||||
|
||||
LoaderTrampoline* trampoline = (LoaderTrampoline*)physicalDevice;
|
||||
VkRpiPhysicalDevice* realPhysicalDevice = trampoline->loaderTerminator->physicalDevice;
|
||||
|
||||
@ -228,7 +228,31 @@ void createWindowSurface() {
|
||||
if (vkCreateRpiSurfaceEXT(physicalDevice) != VK_SUCCESS) {
|
||||
std::cerr << "failed to create window surface!" << std::endl;
|
||||
assert(0);
|
||||
}
|
||||
}*/
|
||||
|
||||
uint32_t displayCount;
|
||||
vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayCount, 0);
|
||||
VkDisplayPropertiesKHR* displayProperties = (VkDisplayPropertiesKHR*)malloc(sizeof(VkDisplayPropertiesKHR)*displayCount);
|
||||
vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayCount, displayProperties);
|
||||
|
||||
uint32_t propertyCount;
|
||||
vkGetDisplayModePropertiesKHR(physicalDevice, displayProperties[0].display, &propertyCount, 0);
|
||||
VkDisplayModePropertiesKHR* displayModeProperties = (VkDisplayModePropertiesKHR*)malloc(sizeof(VkDisplayModePropertiesKHR)*propertyCount);
|
||||
vkGetDisplayModePropertiesKHR(physicalDevice, displayProperties[0].display, &propertyCount, displayModeProperties);
|
||||
|
||||
VkDisplayModeCreateInfoKHR dmci = {};
|
||||
dmci.sType = VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR;
|
||||
dmci.parameters = displayModeProperties[0].parameters;
|
||||
VkDisplayModeKHR displayMode;
|
||||
vkCreateDisplayModeKHR(physicalDevice, displayProperties[0].display, &dmci, 0, &displayMode);
|
||||
|
||||
VkDisplaySurfaceCreateInfoKHR dsci = {};
|
||||
dsci.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR;
|
||||
dsci.displayMode = displayMode;
|
||||
dsci.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
dsci.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
|
||||
dsci.imageExtent = displayModeProperties[0].parameters.visibleRegion;
|
||||
vkCreateDisplayPlaneSurfaceKHR(instance, &dsci, 0, &windowSurface);
|
||||
|
||||
std::cout << "created window surface" << std::endl;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user