tune drm video engine for acclerated graphics

This commit is contained in:
Vincent Wei
2019-07-03 12:17:21 +08:00
parent 5e65422a28
commit 06b90939c4
3 changed files with 221 additions and 112 deletions
+4 -3
View File
@@ -99,20 +99,21 @@ typedef struct _DrmDriverOps {
void (*destroy_driver) (DrmDriver *driver);
uint32_t (* create_buffer) (DrmDriver *driver,
int depth, int bpp,
unsigned int width, unsigned int height,
unsigned int *pitch, BOOL as_fb);
unsigned int *pitch);
BOOL (* fetch_buffer) (DrmDriver *driver,
uint32_t buffer_id,
unsigned int *width, unsigned int *height,
unsigned int *pitch);
BOOL (* map_buffer) (DrmDriver *driver,
uint8_t* (* map_buffer) (DrmDriver *driver,
uint32_t buffer_id);
void (* unmap_buffer) (DrmDriver *driver,
uint32_t buffer_id);
char * (* begin_flush) (DrmDriver *driver,
uint8_t * (* begin_flush) (DrmDriver *driver,
uint32_t buffer_id);
void (* end_flush) (DrmDriver *driver,
+209 -106
View File
@@ -63,14 +63,14 @@ static int DRM_VideoInit(_THIS, GAL_PixelFormat *vformat);
static GAL_Rect **DRM_ListModes(_THIS, GAL_PixelFormat *format, Uint32 flags);
static int DRM_SetColors(_THIS, int firstcolor, int ncolors, GAL_Color *colors);
static void DRM_VideoQuit(_THIS);
static int DRM_Suspend(_THIS);
static int DRM_Resume(_THIS);
/* DRM engine operators for dumb buffer */
static GAL_Surface *DRM_SetVideoMode_Dumb(_THIS, GAL_Surface *current,
int width, int height, int bpp, Uint32 flags);
static int DRM_AllocHWSurface_Dumb(_THIS, GAL_Surface *surface);
static void DRM_FreeHWSurface_Dumb(_THIS, GAL_Surface *surface);
static int DRM_Suspend_Dumb(_THIS);
static int DRM_Resume_Dumb(_THIS);
/* DRM engine operators accelerated */
static GAL_Surface *DRM_SetVideoMode_Accl(_THIS, GAL_Surface *current,
@@ -103,15 +103,6 @@ static int DRM_Available(void)
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct drm_mode_info {
@@ -132,28 +123,6 @@ struct drm_mode_info {
*/
static void drm_cleanup(DrmVideoData* vdata)
{
struct drm_mode_info *iter;
struct drm_mode_destroy_dumb dreq;
if (vdata->modes) {
int i = 0;
while (vdata->modes[i]) {
free (vdata->modes[i]);
i++;
}
free(vdata->modes);
}
while (vdata->mode_list) {
/* remove from global list */
iter = vdata->mode_list;
vdata->mode_list = iter->next;
/* free allocated memory */
free(iter);
}
if (vdata->saved_crtc) {
/* restore saved CRTC configuration */
int ret = drmModeSetCrtc(vdata->dev_fd,
@@ -171,28 +140,59 @@ static void drm_cleanup(DrmVideoData* vdata)
drmModeFreeCrtc(vdata->saved_crtc);
}
if (vdata->fb) {
/* unmap buffer */
munmap(vdata->fb, vdata->size);
if (vdata->scanout_fb) {
if (vdata->driver_ops) {
vdata->driver_ops->unmap_buffer(vdata->driver, vdata->scanout_buff_id);
vdata->driver_ops->destroy_buffer(vdata->driver, vdata->scanout_buff_id);
}
else {
/* dumb buffer */
struct drm_mode_destroy_dumb dreq;
/* delete framebuffer */
drmModeRmFB(vdata->dev_fd, vdata->buff);
/* unmap buffer */
munmap(vdata->scanout_fb, vdata->size);
/* delete dumb buffer */
memset(&dreq, 0, sizeof(dreq));
dreq.handle = vdata->handle;
drmIoctl(vdata->dev_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
/* delete framebuffer */
drmModeRmFB(vdata->dev_fd, vdata->scanout_buff_id);
/* delete dumb buffer */
memset(&dreq, 0, sizeof(dreq));
dreq.handle = vdata->handle;
drmIoctl(vdata->dev_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
}
}
if (vdata->modes) {
int i = 0;
while (vdata->modes[i]) {
free (vdata->modes[i]);
i++;
}
free(vdata->modes);
}
while (vdata->mode_list) {
struct drm_mode_info *iter;
/* remove from global list */
iter = vdata->mode_list;
vdata->mode_list = iter->next;
/* free allocated memory */
free(iter);
}
}
static void DRM_DeleteDevice(GAL_VideoDevice *device)
{
drm_cleanup(device->hidden);
if (device->hidden->driver && device->hidden->driver_ops) {
device->hidden->driver_ops->destroy_driver(device->hidden->driver);
}
drm_cleanup(device->hidden);
free(device->hidden);
free(device);
}
@@ -276,6 +276,7 @@ static int open_drm_device(GAL_VideoDevice *device)
}
device->hidden->dev_fd = device_fd;
device->hidden->driver = NULL;
return 0;
}
@@ -298,7 +299,7 @@ static GAL_VideoDevice *DRM_CreateDevice(int devindex)
if ( device ) {
memset(device, 0, (sizeof (*device)));
device->hidden = (struct GAL_PrivateVideoData *)
malloc((sizeof (*device->hidden)));
calloc(1, (sizeof (*device->hidden)));
}
if ((device == NULL) || (device->hidden == NULL)) {
GAL_OutOfMemory();
@@ -337,6 +338,8 @@ static GAL_VideoDevice *DRM_CreateDevice(int devindex)
device->SetHWColorKey = DRM_SetHWColorKey_Accl;
device->SetHWAlpha = DRM_SetHWAlpha_Accl;
device->FreeHWSurface = DRM_FreeHWSurface_Accl;
device->Suspend = DRM_Suspend;
device->Resume = DRM_Resume;
}
else {
/* Use DUMB buffer */
@@ -350,8 +353,8 @@ static GAL_VideoDevice *DRM_CreateDevice(int devindex)
device->SetHWColorKey = NULL;
device->SetHWAlpha = NULL;
device->FreeHWSurface = DRM_FreeHWSurface_Dumb;
device->Suspend = DRM_Suspend_Dumb;
device->Resume = DRM_Resume_Dumb;
device->Suspend = DRM_Suspend;
device->Resume = DRM_Resume;
}
device->free = DRM_DeleteDevice;
@@ -609,6 +612,59 @@ static void DRM_VideoQuit(_THIS)
}
}
static int DRM_Resume(_THIS)
{
DrmVideoData* vdata = this->hidden;
int ret = -1;
_DBG_PRINTF ("NEWGAL>DRM: %s called\n", __FUNCTION__);
if (vdata->saved_info) {
vdata->saved_crtc = drmModeGetCrtc(vdata->dev_fd,
vdata->saved_info->crtc);
ret = drmModeSetCrtc(vdata->dev_fd,
vdata->saved_info->crtc,
vdata->scanout_buff_id, 0, 0,
&vdata->saved_info->conn, 1,
&vdata->saved_info->mode);
}
if (ret) {
_ERR_PRINTF ("NEWGAL>DRM: Failed to resume dumb frame buffer: %d.\n",
ret);
}
return ret;
}
static int DRM_Suspend(_THIS)
{
DrmVideoData* vdata = this->hidden;
int ret = -1;
_DBG_PRINTF ("NEWGAL>DRM: %s called\n", __FUNCTION__);
if (vdata->saved_crtc) {
/* restore saved CRTC configuration */
ret = drmModeSetCrtc(vdata->dev_fd,
vdata->saved_crtc->crtc_id,
vdata->saved_crtc->buffer_id,
vdata->saved_crtc->x,
vdata->saved_crtc->y,
&vdata->saved_info->conn, 1,
&vdata->saved_crtc->mode);
drmModeFreeCrtc(vdata->saved_crtc);
vdata->saved_crtc = NULL;
}
if (ret) {
_ERR_PRINTF ("NEWGAL>DRM: Failed to suspend dumb frame buffer: %m.\n");
}
return ret;
}
/*
* drm_create_dumb_fb(vdata, info):
* Call this function to create a so called "dumb buffer".
@@ -643,7 +699,7 @@ static int drm_create_dumb_fb(DrmVideoData* vdata, const DrmModeInfo* info,
/* create framebuffer object for the dumb-buffer */
ret = drmModeAddFB(vdata->dev_fd, vdata->width, vdata->height, depth, bpp,
vdata->pitch, vdata->handle, &vdata->buff);
vdata->pitch, vdata->handle, &vdata->scanout_buff_id);
if (ret) {
_ERR_PRINTF("NEWGAL>DRM: cannot create framebuffer (%d): %m\n",
errno);
@@ -662,9 +718,9 @@ static int drm_create_dumb_fb(DrmVideoData* vdata, const DrmModeInfo* info,
}
/* perform actual memory mapping */
vdata->fb = mmap(0, vdata->size, PROT_READ | PROT_WRITE, MAP_SHARED,
vdata->scanout_fb = mmap(0, vdata->size, PROT_READ | PROT_WRITE, MAP_SHARED,
vdata->dev_fd, mreq.offset);
if (vdata->fb == MAP_FAILED) {
if (vdata->scanout_fb == MAP_FAILED) {
_ERR_PRINTF("NEWGAL>DRM: cannot mmap dumb buffer (%d): %m\n", errno);
ret = -errno;
goto err_fb;
@@ -673,7 +729,7 @@ static int drm_create_dumb_fb(DrmVideoData* vdata, const DrmModeInfo* info,
return 0;
err_fb:
drmModeRmFB(vdata->dev_fd, vdata->buff);
drmModeRmFB(vdata->dev_fd, vdata->scanout_buff_id);
err_destroy:
memset(&dreq, 0, sizeof(dreq));
@@ -729,7 +785,7 @@ static GAL_Surface *DRM_SetVideoMode_Dumb(_THIS, GAL_Surface *current,
/* perform actual modesetting on the found connector+CRTC */
this->hidden->saved_crtc = drmModeGetCrtc(vdata->dev_fd, info->crtc);
ret = drmModeSetCrtc(vdata->dev_fd, info->crtc, vdata->buff, 0, 0,
ret = drmModeSetCrtc(vdata->dev_fd, info->crtc, vdata->scanout_buff_id, 0, 0,
&info->conn, 1, &info->mode);
if (ret) {
_ERR_PRINTF ("NEWGAL>DRM: cannot set CRTC for connector %u (%d): %m\n",
@@ -755,7 +811,7 @@ static GAL_Surface *DRM_SetVideoMode_Dumb(_THIS, GAL_Surface *current,
current->w = width;
current->h = height;
current->pitch = this->hidden->pitch;
current->pixels = this->hidden->fb;
current->pixels = this->hidden->scanout_fb;
/* We're done */
return(current);
@@ -771,63 +827,110 @@ static void DRM_FreeHWSurface_Dumb(_THIS, GAL_Surface *surface)
surface->pixels = NULL;
}
static int DRM_Resume_Dumb(_THIS)
{
DrmVideoData* vdata = this->hidden;
int ret = -1;
_DBG_PRINTF ("NEWGAL>DRM: %s called\n", __FUNCTION__);
if (vdata->saved_info) {
vdata->saved_crtc = drmModeGetCrtc(vdata->dev_fd,
vdata->saved_info->crtc);
ret = drmModeSetCrtc(vdata->dev_fd,
vdata->saved_info->crtc,
vdata->buff, 0, 0,
&vdata->saved_info->conn, 1,
&vdata->saved_info->mode);
}
if (ret) {
_ERR_PRINTF ("NEWGAL>DRM: Failed to resume dumb frame buffer: %d.\n",
ret);
}
return ret;
}
static int DRM_Suspend_Dumb(_THIS)
{
DrmVideoData* vdata = this->hidden;
int ret = -1;
_DBG_PRINTF ("NEWGAL>DRM: %s called\n", __FUNCTION__);
if (vdata->saved_crtc) {
/* restore saved CRTC configuration */
ret = drmModeSetCrtc(vdata->dev_fd,
vdata->saved_crtc->crtc_id,
vdata->saved_crtc->buffer_id,
vdata->saved_crtc->x,
vdata->saved_crtc->y,
&vdata->saved_info->conn, 1,
&vdata->saved_crtc->mode);
drmModeFreeCrtc(vdata->saved_crtc);
vdata->saved_crtc = NULL;
}
if (ret) {
_ERR_PRINTF ("NEWGAL>DRM: Failed to suspend dumb frame buffer: %m.\n");
}
return ret;
}
/* DRM engine methods for accelerated buffers */
static GAL_Surface *DRM_SetVideoMode_Accl(_THIS, GAL_Surface *current,
int width, int height, int bpp, Uint32 flags)
{
DrmVideoData* vdata = this->hidden;
DrmModeInfo* info;
int depth;
unsigned int pitch;
if (bpp != 32) {
_DBG_PRINTF("NEWGAL>DRM: force bpp (%d) to be 32\n", bpp);
bpp = 32;
}
depth = 24;
/* find the connector+CRTC suitable for the resolution requested */
info = find_mode(vdata, width, height);
if (info == NULL) {
_ERR_PRINTF("NEWGAL>DRM: cannot find a CRTC for video mode: %dx%d-%dbpp\n",
width, height, bpp);
return NULL;
}
_DBG_PRINTF("NEWGAL>DRM: going setting video mode: %dx%d-%dbpp\n",
info->width, info->height, bpp);
#if 0
if (drmSetMaster(this->hidden->dev_fd)) {
_ERR_PRINTF("NEWGAL>DRM: failed to call drmSetMaster: %m\n");
return NULL;
}
#endif
/* create the scanout buffer and set up it as frame buffer */
vdata->scanout_buff_id =
vdata->driver_ops->create_buffer(vdata->driver, depth, bpp,
info->width, info->height, &pitch);
if (vdata->scanout_buff_id == 0) {
goto error;
}
vdata->width = info->width;
vdata->height = info->height;
vdata->bpp = bpp;
vdata->pitch = pitch;
vdata->size = pitch * info->height;
vdata->handle = 0;
vdata->scanout_fb = vdata->driver_ops->map_buffer(vdata->driver, vdata->scanout_buff_id);
if (vdata->scanout_fb == NULL) {
_ERR_PRINTF ("NEWGAL>DRM: cannot map scanout frame buffer: %m\n");
goto error;
}
_DBG_PRINTF("NEWGAL>DRM: scanout frame buffer: size (%dx%d), pitch(%d)\n",
vdata->width, vdata->height, vdata->pitch);
/* get console buffer id */
vdata->saved_crtc = drmModeGetCrtc(vdata->dev_fd, info->crtc);
vdata->console_buff_id = vdata->saved_crtc->buffer_id;
/* perform actual modesetting on the found connector+CRTC */
if (drmModeSetCrtc(vdata->dev_fd, info->crtc, vdata->scanout_buff_id, 0, 0,
&info->conn, 1, &info->mode)) {
_ERR_PRINTF ("NEWGAL>DRM: cannot set CRTC for connector %u (%d): %m\n",
info->conn, errno);
goto error;
}
this->hidden->saved_info = info;
/* Allocate the new pixel format for the screen */
if (!GAL_ReallocFormat (current, bpp, 0, 0, 0, 0)) {
goto error;
}
_DBG_PRINTF("NEWGAL>DRM: real screen mode: %dx%d-%dbpp\n", width, height, bpp);
current->flags = flags & GAL_FULLSCREEN;
current->w = width;
current->h = height;
current->pitch = this->hidden->pitch;
current->pixels = this->hidden->scanout_fb;
/* We're done */
return(current);
error:
if (vdata->saved_crtc) {
drmModeFreeCrtc(vdata->saved_crtc);
vdata->saved_crtc = NULL;
}
if (vdata->scanout_fb) {
vdata->driver_ops->unmap_buffer(vdata->driver, vdata->scanout_buff_id);
vdata->scanout_fb = NULL;
}
if (vdata->scanout_buff_id) {
vdata->driver_ops->destroy_buffer(vdata->driver, vdata->scanout_buff_id);
vdata->scanout_buff_id = 0;
}
return NULL;
}
+8 -3
View File
@@ -63,12 +63,17 @@ typedef struct GAL_PrivateVideoData {
uint32_t pitch;
uint32_t size;
uint32_t buff;
uint32_t handle;
uint32_t scanout_buff_id;
uint8_t* scanout_fb;
DrmModeInfo* saved_info;
drmModeCrtc* saved_crtc;
uint8_t* fb;
/* only valid when using DUMB frame buffer */
uint32_t handle;
/* only valid when using DRM driver */
uint32_t console_buff_id;
} DrmVideoData;
#endif /* _NEWGAL_DRMVIDEO_H */