mirror of
https://github.com/Yours3lf/rpi-vk-driver.git
synced 2025-03-21 12:29:15 +01:00
updated modeset, vc4 kernel interface added
This commit is contained in:
parent
cfd2749134
commit
8dde5b888d
@ -2,28 +2,19 @@
|
||||
#include "CustomAssert.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <drm/vc4_drm.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "vkExt.h"
|
||||
|
||||
#include "modeset.h"
|
||||
#include "kernelInterface.h"
|
||||
|
||||
#include "AlignedAllocator.h"
|
||||
#include "PoolAllocator.h"
|
||||
#include "LinearAllocator.h"
|
||||
|
||||
#include "drm/vc4_drm.h"
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) (a < b ? a : b)
|
||||
#endif
|
||||
@ -32,26 +23,6 @@
|
||||
#define max(a, b) (a > b ? a : b)
|
||||
#endif
|
||||
|
||||
#define DRM_IOCTL_FILE_NAME "/dev/"DRM_NAME
|
||||
|
||||
static int fd = -1;
|
||||
|
||||
int openIoctl()
|
||||
{
|
||||
fd = open(DRM_IOCTL_FILE_NAME, O_RDWR);
|
||||
if (fd < 0) {
|
||||
printf("Can't open device file: %s\n", DRM_IOCTL_FILE_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void closeIoctl(int fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
VkPhysicalDeviceLimits _limits =
|
||||
{
|
||||
//TODO these values might change
|
||||
@ -250,7 +221,7 @@ typedef struct VkCommandBuffer_T
|
||||
//Recorded commands include commands to bind pipelines and descriptor sets to the command buffer, commands to modify dynamic state, commands to draw (for graphics rendering),
|
||||
//commands to dispatch (for compute), commands to execute secondary command buffers (for primary command buffers only), commands to copy buffers and images, and other commands
|
||||
|
||||
drm_vc4_submit_cl cls[100]; //each cl is a draw call
|
||||
struct drm_vc4_submit_cl cls[100]; //each cl is a draw call
|
||||
unsigned numClsUsed;
|
||||
commandBufferState state;
|
||||
VkCommandBufferUsageFlags usageFlags;
|
||||
@ -473,6 +444,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
|
||||
//TODO ignored for now
|
||||
//pCreateInfo->pApplicationInfo
|
||||
|
||||
int ret = openIoctl(); assert(!ret);
|
||||
|
||||
int chip_info = vc4_get_chip_info(renderFd);
|
||||
int has_tiling = vc4_test_tiling(renderFd);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
@ -666,8 +642,7 @@ VkResult vkCreateRpiSurfaceKHR(
|
||||
//TODO: allocator is ignored for now
|
||||
assert(pAllocator == 0);
|
||||
|
||||
int ret = modeset_open("/dev/dri/card0"); assert(!ret);
|
||||
*pSurface = (VkSurfaceKHR)modeset_create();
|
||||
*pSurface = (VkSurfaceKHR)modeset_create(controlFd);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
@ -689,8 +664,7 @@ VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(
|
||||
//TODO: allocator is ignored for now
|
||||
assert(pAllocator == 0);
|
||||
|
||||
modeset_destroy((modeset_dev*)surface);
|
||||
modeset_close();
|
||||
modeset_destroy(controlFd, (modeset_dev*)surface);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1330,7 +1304,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
|
||||
for(int c = 0; c < pPresentInfo->swapchainCount; ++c)
|
||||
{
|
||||
//TODO
|
||||
modeset_swapbuffer((modeset_dev*)pPresentInfo->pSwapchains[c], pPresentInfo->pImageIndices[c]);
|
||||
modeset_swapbuffer(controlFd, (modeset_dev*)pPresentInfo->pSwapchains[c], pPresentInfo->pImageIndices[c]);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
@ -1479,5 +1453,6 @@ VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
|
||||
assert(pAllocator == 0);
|
||||
|
||||
//TODO
|
||||
closeIoctl();
|
||||
}
|
||||
|
||||
|
368
driver/kernelInterface.c
Normal file
368
driver/kernelInterface.c
Normal file
@ -0,0 +1,368 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "kernelInterface.h"
|
||||
|
||||
int controlFd = -1;
|
||||
int renderFd = -1;
|
||||
|
||||
int openIoctl()
|
||||
{
|
||||
controlFd = open(DRM_IOCTL_CTRL_DEV_FILE_NAME, O_RDWR | O_CLOEXEC);
|
||||
if (controlFd < 0) {
|
||||
printf("Can't open device file: %s\n", DRM_IOCTL_CTRL_DEV_FILE_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
renderFd = open(DRM_IOCTL_RENDER_DEV_FILE_NAME, O_RDWR | O_CLOEXEC);
|
||||
if (renderFd < 0) {
|
||||
printf("Can't open device file: %s\n", DRM_IOCTL_RENDER_DEV_FILE_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void closeIoctl()
|
||||
{
|
||||
close(controlFd);
|
||||
close(renderFd);
|
||||
}
|
||||
|
||||
int vc4_get_chip_info(int fd)
|
||||
{
|
||||
struct drm_vc4_get_param ident0 = {
|
||||
.param = DRM_VC4_PARAM_V3D_IDENT0,
|
||||
};
|
||||
struct drm_vc4_get_param ident1 = {
|
||||
.param = DRM_VC4_PARAM_V3D_IDENT1,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = drmIoctl(fd, DRM_IOCTL_VC4_GET_PARAM, &ident0);
|
||||
if (ret != 0) {
|
||||
if (errno == EINVAL) {
|
||||
/* Backwards compatibility with 2835 kernels which
|
||||
* only do V3D 2.1.
|
||||
*/
|
||||
return 21;
|
||||
} else {
|
||||
printf("Couldn't get V3D IDENT0: %s\n",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ret = drmIoctl(fd, DRM_IOCTL_VC4_GET_PARAM, &ident1);
|
||||
if (ret != 0) {
|
||||
printf("Couldn't get V3D IDENT1: %s\n",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t major = (ident0.value >> 24) & 0xff;
|
||||
uint32_t minor = (ident1.value >> 0) & 0xf;
|
||||
uint32_t v3d_ver = major * 10 + minor;
|
||||
|
||||
if (v3d_ver != 21 && v3d_ver != 26) {
|
||||
printf("V3D %d.%d not supported.\n",
|
||||
v3d_ver / 10,
|
||||
v3d_ver % 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return v3d_ver;
|
||||
}
|
||||
|
||||
int vc4_has_feature(int fd, uint32_t feature)
|
||||
{
|
||||
struct drm_vc4_get_param p = {
|
||||
.param = feature,
|
||||
};
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_VC4_GET_PARAM, &p);
|
||||
|
||||
if (ret != 0)
|
||||
return 0;
|
||||
|
||||
return p.value;
|
||||
}
|
||||
|
||||
int vc4_test_tiling(int fd)
|
||||
{
|
||||
/* Test if the kernel has GET_TILING; it will return -EINVAL if the
|
||||
* ioctl does not exist, but -ENOENT if we pass an impossible handle.
|
||||
* 0 cannot be a valid GEM object, so use that.
|
||||
*/
|
||||
struct drm_vc4_get_tiling get_tiling = {
|
||||
.handle = 0x0,
|
||||
};
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_VC4_GET_TILING, &get_tiling);
|
||||
if (ret == -1 && errno == ENOENT)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t vc4_bo_get_tiling(int fd, uint32_t bo, uint64_t mod)
|
||||
{
|
||||
struct drm_vc4_get_tiling get_tiling = {
|
||||
.handle = bo,
|
||||
};
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_VC4_GET_TILING, &get_tiling);
|
||||
|
||||
//TODO
|
||||
if (ret != 0) {
|
||||
return DRM_FORMAT_MOD_LINEAR;
|
||||
} else if (mod == DRM_FORMAT_MOD_INVALID) {
|
||||
return get_tiling.modifier;
|
||||
} else if (mod != get_tiling.modifier) {
|
||||
printf("Modifier 0x%llx vs. tiling (0x%llx) mismatch\n",
|
||||
(long long)mod, get_tiling.modifier);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int vc4_bo_set_tiling(int fd, uint32_t bo, uint64_t mod)
|
||||
{
|
||||
struct drm_vc4_set_tiling set_tiling = {
|
||||
.handle = bo,
|
||||
.modifier = mod,
|
||||
};
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_VC4_SET_TILING,
|
||||
&set_tiling);
|
||||
if (ret != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* vc4_bo_map_unsynchronized(int fd, uint32_t bo, uint32_t size)
|
||||
{
|
||||
uint64_t offset;
|
||||
int ret;
|
||||
|
||||
//if (bo->map)
|
||||
// return bo->map;
|
||||
|
||||
struct drm_vc4_mmap_bo map;
|
||||
memset(&map, 0, sizeof(map));
|
||||
map.handle = bo;
|
||||
ret = drmIoctl(fd, DRM_IOCTL_VC4_MMAP_BO, &map);
|
||||
offset = map.offset;
|
||||
if (ret != 0) {
|
||||
printf("map ioctl failure\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* mapPtr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
fd, offset);
|
||||
if (mapPtr == MAP_FAILED) {
|
||||
printf("mmap of bo %d (offset 0x%016llx, size %d) failed\n",
|
||||
bo, (long long)offset, size);
|
||||
return 0;
|
||||
}
|
||||
//VG(VALGRIND_MALLOCLIKE_BLOCK(bo->map, bo->size, 0, false));
|
||||
|
||||
return mapPtr;
|
||||
}
|
||||
|
||||
int vc4_bo_wait_ioctl(int fd, uint32_t handle, uint64_t timeout_ns)
|
||||
{
|
||||
struct drm_vc4_wait_bo wait = {
|
||||
.handle = handle,
|
||||
.timeout_ns = timeout_ns,
|
||||
};
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_VC4_WAIT_BO, &wait);
|
||||
if (ret == -1)
|
||||
{
|
||||
printf("bo wait fail: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int vc4_seqno_wait_ioctl(int fd, uint64_t seqno, uint64_t timeout_ns)
|
||||
{
|
||||
struct drm_vc4_wait_seqno wait = {
|
||||
.seqno = seqno,
|
||||
.timeout_ns = timeout_ns,
|
||||
};
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_VC4_WAIT_SEQNO, &wait);
|
||||
if (ret == -1)
|
||||
{
|
||||
printf("bo wait fail: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int vc4_bo_flink(int fd, uint32_t bo, uint32_t *name)
|
||||
{
|
||||
struct drm_gem_flink flink = {
|
||||
.handle = bo,
|
||||
};
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
|
||||
if (ret) {
|
||||
printf("Failed to flink bo %d: %s\n",
|
||||
bo, strerror(errno));
|
||||
//free(bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//bo->private = false;
|
||||
*name = flink.name;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t vc4_bo_alloc_shader(int fd, const void *data, uint32_t* size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
//TODO
|
||||
uint32_t alignedSize = *size;//align(*size, 4096);
|
||||
|
||||
struct drm_vc4_create_shader_bo create = {
|
||||
.size = *size, //TODO why isn't this alignedSize?
|
||||
.data = (uintptr_t)data,
|
||||
};
|
||||
|
||||
ret = drmIoctl(fd, DRM_IOCTL_VC4_CREATE_SHADER_BO,
|
||||
&create);
|
||||
|
||||
if (ret != 0) {
|
||||
printf("create shader ioctl failure\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*size = alignedSize;
|
||||
|
||||
return create.handle;
|
||||
}
|
||||
|
||||
uint32_t vc4_bo_open_name(int fd, uint32_t name)
|
||||
//uint32_t winsys_stride)
|
||||
{
|
||||
struct drm_gem_open o = {
|
||||
.name = name
|
||||
};
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_GEM_OPEN, &o);
|
||||
if (ret) {
|
||||
printf("Failed to open bo %d: %s\n",
|
||||
name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO
|
||||
//return vc4_bo_open_handle(screen, winsys_stride, o.handle, o.size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t vc4_bo_alloc(int fd, uint32_t size, const char *name)
|
||||
{
|
||||
int cleared_and_retried = 0;
|
||||
struct drm_vc4_create_bo create;
|
||||
int ret;
|
||||
|
||||
//TODO
|
||||
uint32_t alignedSize = size;//align(size, 4096);
|
||||
|
||||
/*bo = vc4_bo_from_cache(screen, size, name);
|
||||
if (bo) {
|
||||
if (dump_stats) {
|
||||
fprintf(stderr, "Allocated %s %dkb from cache:\n",
|
||||
name, size / 1024);
|
||||
vc4_bo_dump_stats(screen);
|
||||
}
|
||||
return bo;
|
||||
}*/
|
||||
|
||||
memset(&create, 0, sizeof(create));
|
||||
create.size = alignedSize;
|
||||
|
||||
ret = drmIoctl(fd, DRM_IOCTL_VC4_CREATE_BO, &create);
|
||||
uint32_t handle = create.handle;
|
||||
|
||||
if (ret != 0) {
|
||||
/*if (!list_empty(&screen->bo_cache.time_list) &&
|
||||
!cleared_and_retried) {
|
||||
cleared_and_retried = true;
|
||||
vc4_bo_cache_free_all(&screen->bo_cache);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
free(bo);*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO
|
||||
//vc4_bo_label(screen, bo, "%s", name);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void vc4_bo_free(int fd, uint32_t bo, void* mappedAddr, uint32_t size)
|
||||
{
|
||||
if (mappedAddr) {
|
||||
munmap(mappedAddr, size);
|
||||
//VG(VALGRIND_FREELIKE_BLOCK(bo->map, 0));
|
||||
}
|
||||
|
||||
struct drm_gem_close c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.handle = bo;
|
||||
int ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &c);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("close object %d: %s\n", bo, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int vc4_bo_unpurgeable(int fd, uint32_t bo, int hasMadvise)
|
||||
{
|
||||
struct drm_vc4_gem_madvise arg = {
|
||||
.handle = bo,
|
||||
.madv = VC4_MADV_WILLNEED,
|
||||
};
|
||||
|
||||
if (!hasMadvise)
|
||||
return 1;
|
||||
|
||||
if (drmIoctl(fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg))
|
||||
return 0;
|
||||
|
||||
return arg.retained;
|
||||
}
|
||||
|
||||
void vc4_bo_purgeable(int fd, uint32_t bo, int hasMadvise)
|
||||
{
|
||||
struct drm_vc4_gem_madvise arg = {
|
||||
.handle = bo,
|
||||
.madv = VC4_MADV_DONTNEED,
|
||||
};
|
||||
|
||||
if (hasMadvise)
|
||||
{
|
||||
drmIoctl(fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg);
|
||||
}
|
||||
}
|
||||
|
||||
void vc4_bo_label(int fd, uint32_t bo, const char* name)
|
||||
{
|
||||
//TODO don't use in release!
|
||||
|
||||
struct drm_vc4_label_bo label = {
|
||||
.handle = bo,
|
||||
.len = strlen(name),
|
||||
.name = (uintptr_t)name,
|
||||
};
|
||||
drmIoctl(fd, DRM_IOCTL_VC4_LABEL_BO, &label);
|
||||
}
|
52
driver/kernelInterface.h
Normal file
52
driver/kernelInterface.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "CustomAssert.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/vc4_drm.h>
|
||||
|
||||
#define DRM_IOCTL_CTRL_DEV_FILE_NAME "/dev/dri/card0"
|
||||
#define DRM_IOCTL_RENDER_DEV_FILE_NAME "/dev/dri/renderD128" //TODO does this need to be dynamic? (eg. iterate through renderDn?)
|
||||
|
||||
extern int controlFd;
|
||||
extern int renderFd;
|
||||
|
||||
int openIoctl();
|
||||
void closeIoctl();
|
||||
|
||||
int vc4_get_chip_info(int fd);
|
||||
int vc4_has_feature(int fd, uint32_t feature);
|
||||
int vc4_test_tiling(int fd);
|
||||
uint64_t vc4_bo_get_tiling(int fd, uint32_t bo, uint64_t mod);
|
||||
int vc4_bo_set_tiling(int fd, uint32_t bo, uint64_t mod);
|
||||
void* vc4_bo_map_unsynchronized(int fd, uint32_t bo, uint32_t size);
|
||||
int vc4_bo_wait_ioctl(int fd, uint32_t handle, uint64_t timeout_ns);
|
||||
int vc4_seqno_wait_ioctl(int fd, uint64_t seqno, uint64_t timeout_ns);
|
||||
int vc4_bo_flink(int fd, uint32_t bo, uint32_t *name);
|
||||
uint32_t vc4_bo_alloc_shader(int fd, const void *data, uint32_t* size);
|
||||
uint32_t vc4_bo_open_name(int fd, uint32_t name);
|
||||
uint32_t vc4_bo_alloc(int fd, uint32_t size, const char *name);
|
||||
void vc4_bo_free(int fd, uint32_t bo, void* mappedAddr, uint32_t size);
|
||||
int vc4_bo_unpurgeable(int fd, uint32_t bo, int hasMadvise);
|
||||
void vc4_bo_purgeable(int fd, uint32_t bo, int hasMadvise);
|
||||
void vc4_bo_label(int fd, uint32_t bo, const char* name);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
@ -49,13 +49,11 @@
|
||||
|
||||
//static struct modeset_dev *modeset_list = NULL;
|
||||
|
||||
static int fd = -1;
|
||||
|
||||
static int modeset_find_crtc(drmModeRes *res, drmModeConnector *conn,
|
||||
static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
|
||||
struct modeset_dev *dev);
|
||||
static int modeset_create_fb(struct modeset_buf *buf);
|
||||
static void modeset_destroy_fb(struct modeset_buf *buf);
|
||||
static int modeset_setup_dev(drmModeRes *res, drmModeConnector *conn,
|
||||
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);
|
||||
|
||||
|
||||
@ -84,27 +82,7 @@ static int modeset_setup_dev(drmModeRes *res, drmModeConnector *conn,
|
||||
* nvidia, intel, etc. specific code, we depend on DUMB_BUFFERs here.
|
||||
*/
|
||||
|
||||
int modeset_open(const char *node)
|
||||
{
|
||||
uint64_t has_dumb;
|
||||
|
||||
fd = open(node, O_RDWR);
|
||||
if (fd < 0) {
|
||||
printf("cannot open '%s': %m\n", node);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || !has_dumb) {
|
||||
printf("drm device '%s' does not support dumb buffers\n", node);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
modeset_dev* modeset_create()
|
||||
modeset_dev* modeset_create(int fd)
|
||||
{
|
||||
modeset_dev* ret_dev = 0;
|
||||
drmModeRes *res;
|
||||
@ -112,6 +90,12 @@ modeset_dev* modeset_create()
|
||||
struct modeset_dev *dev;
|
||||
int ret;
|
||||
|
||||
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) {
|
||||
@ -134,7 +118,7 @@ modeset_dev* modeset_create()
|
||||
dev->conn = conn->connector_id;
|
||||
|
||||
// call helper function to prepare this connector
|
||||
ret = modeset_setup_dev(res, conn, dev);
|
||||
ret = modeset_setup_dev(fd, res, conn, dev);
|
||||
if (ret) {
|
||||
if (ret != -ENOENT) {
|
||||
errno = -ret;
|
||||
@ -177,7 +161,7 @@ modeset_dev* modeset_create()
|
||||
* modeset_create_fb() can use them without requiring a pointer to modeset_dev.
|
||||
*/
|
||||
|
||||
static int modeset_setup_dev(drmModeRes *res, drmModeConnector *conn,
|
||||
static int modeset_setup_dev(int fd, drmModeRes *res, drmModeConnector *conn,
|
||||
struct modeset_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
@ -206,7 +190,7 @@ static int modeset_setup_dev(drmModeRes *res, drmModeConnector *conn,
|
||||
conn->connector_id, dev->bufs[0].width, dev->bufs[0].height);
|
||||
|
||||
// find a crtc for this connector
|
||||
ret = modeset_find_crtc(res, conn, dev);
|
||||
ret = modeset_find_crtc(fd, res, conn, dev);
|
||||
if (ret) {
|
||||
printf("no valid crtc for connector %u\n",
|
||||
conn->connector_id);
|
||||
@ -214,7 +198,7 @@ static int modeset_setup_dev(drmModeRes *res, drmModeConnector *conn,
|
||||
}
|
||||
|
||||
// create framebuffer #1 for this CRTC
|
||||
ret = modeset_create_fb(&dev->bufs[0]);
|
||||
ret = modeset_create_fb(fd, &dev->bufs[0]);
|
||||
if (ret) {
|
||||
printf("cannot create framebuffer for connector %u\n",
|
||||
conn->connector_id);
|
||||
@ -222,11 +206,11 @@ static int modeset_setup_dev(drmModeRes *res, drmModeConnector *conn,
|
||||
}
|
||||
|
||||
// create framebuffer #2 for this CRTC
|
||||
ret = modeset_create_fb(&dev->bufs[1]);
|
||||
ret = modeset_create_fb(fd, &dev->bufs[1]);
|
||||
if (ret) {
|
||||
printf("cannot create framebuffer for connector %u\n",
|
||||
conn->connector_id);
|
||||
modeset_destroy_fb(&dev->bufs[0]);
|
||||
modeset_destroy_fb(fd, &dev->bufs[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -237,7 +221,7 @@ static int modeset_setup_dev(drmModeRes *res, drmModeConnector *conn,
|
||||
* modeset_find_crtc() stays the same.
|
||||
*/
|
||||
|
||||
static int modeset_find_crtc(drmModeRes *res, drmModeConnector *conn,
|
||||
static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
|
||||
modeset_dev *dev)
|
||||
{
|
||||
drmModeEncoder *enc;
|
||||
@ -321,7 +305,7 @@ static int modeset_find_crtc(drmModeRes *res, drmModeConnector *conn,
|
||||
* modeset_setup_dev() so we can use them here.
|
||||
*/
|
||||
|
||||
static int modeset_create_fb(struct modeset_buf *buf)
|
||||
static int modeset_create_fb(int fd, struct modeset_buf *buf)
|
||||
{
|
||||
struct drm_mode_create_dumb creq;
|
||||
struct drm_mode_destroy_dumb dreq;
|
||||
@ -401,7 +385,7 @@ static int modeset_create_fb(struct modeset_buf *buf)
|
||||
* We simply unmap the buffer, remove the drm-FB and destroy the memory buffer.
|
||||
*/
|
||||
|
||||
static void modeset_destroy_fb(struct modeset_buf *buf)
|
||||
static void modeset_destroy_fb(int fd, struct modeset_buf *buf)
|
||||
{
|
||||
struct drm_mode_destroy_dumb dreq;
|
||||
|
||||
@ -451,7 +435,7 @@ static void modeset_destroy_fb(struct modeset_buf *buf)
|
||||
* vertical-sync.
|
||||
*/
|
||||
|
||||
void modeset_swapbuffer(modeset_dev* dev, unsigned index)
|
||||
void modeset_swapbuffer(int fd, modeset_dev* dev, unsigned index)
|
||||
{
|
||||
//TODO use index!!
|
||||
|
||||
@ -477,7 +461,7 @@ void modeset_swapbuffer(modeset_dev* dev, unsigned index)
|
||||
* modeset_destroy_fb() instead of accessing the framebuffers directly.
|
||||
*/
|
||||
|
||||
void modeset_destroy(modeset_dev* dev)
|
||||
void modeset_destroy(int fd, modeset_dev* dev)
|
||||
{
|
||||
struct modeset_dev *iter;
|
||||
|
||||
@ -498,19 +482,14 @@ void modeset_destroy(modeset_dev* dev)
|
||||
drmModeFreeCrtc(iter->saved_crtc);
|
||||
|
||||
// destroy framebuffers
|
||||
modeset_destroy_fb(&iter->bufs[1]);
|
||||
modeset_destroy_fb(&iter->bufs[0]);
|
||||
modeset_destroy_fb(fd, &iter->bufs[1]);
|
||||
modeset_destroy_fb(fd, &iter->bufs[0]);
|
||||
|
||||
// free allocated memory
|
||||
free(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void modeset_close()
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* This was a very short extension to the basic modesetting example that shows
|
||||
* how double-buffering is implemented. Double-buffering is the de-facto
|
||||
|
@ -39,11 +39,9 @@ typedef struct modeset_dev {
|
||||
drmModeCrtc *saved_crtc;
|
||||
} modeset_dev;
|
||||
|
||||
int modeset_open(const char* node);
|
||||
modeset_dev* modeset_create();
|
||||
void modeset_swapbuffer(modeset_dev* dev, unsigned index);
|
||||
void modeset_destroy(modeset_dev* dev);
|
||||
void modeset_close();
|
||||
modeset_dev* modeset_create(int fd);
|
||||
void modeset_swapbuffer(int fd, modeset_dev* dev, unsigned index);
|
||||
void modeset_destroy(int fd, modeset_dev* dev);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user