From ee40b20e7aff5dc9d11230e991355c338a64da00 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 24 Nov 2009 12:47:38 +0100 Subject: [PATCH] st/xorg: Add libkms integration --- src/gallium/state_trackers/xorg/Makefile | 3 + src/gallium/state_trackers/xorg/xorg_crtc.c | 69 ++- src/gallium/state_trackers/xorg/xorg_driver.c | 392 ++++++++++++------ .../state_trackers/xorg/xorg_tracker.h | 11 + 4 files changed, 353 insertions(+), 122 deletions(-) diff --git a/src/gallium/state_trackers/xorg/Makefile b/src/gallium/state_trackers/xorg/Makefile index 22c107370e8..cb2c3aea410 100644 --- a/src/gallium/state_trackers/xorg/Makefile +++ b/src/gallium/state_trackers/xorg/Makefile @@ -7,6 +7,9 @@ LIBRARY_INCLUDES = \ -DHAVE_CONFIG_H \ $(shell pkg-config xextproto --atleast-version=7.0.99.1 \ && echo "-DHAVE_XEXTPROTO_71") \ + $(shell pkg-config libkms --atleast-version=1.0 \ + && echo "-DHAVE_LIBKMS") \ + $(shell pkg-config libkms --silence-errors --cflags-only-I) \ $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \ -I$(TOP)/src/gallium/include \ -I$(TOP)/src/gallium/auxiliary \ diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index 2db8d45b3bb..ddcaedde37e 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -52,12 +52,18 @@ #include "pipe/p_inlines.h" #include "util/u_rect.h" +#ifdef HAVE_LIBKMS +#include "libkms.h" +#endif + struct crtc_private { drmModeCrtcPtr drm_crtc; /* hwcursor */ struct pipe_texture *cursor_tex; + struct kms_bo *cursor_bo; + unsigned cursor_handle; }; @@ -174,7 +180,7 @@ crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) } static void -crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) +crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) { unsigned char *ptr; modesettingPtr ms = modesettingPTR(crtc->scrn); @@ -217,13 +223,63 @@ crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) ms->screen->tex_transfer_destroy(transfer); } +#if HAVE_LIBKMS +static void +crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image) +{ + modesettingPtr ms = modesettingPTR(crtc->scrn); + struct crtc_private *crtcp = crtc->driver_private; + unsigned char *ptr; + + if (!crtcp->cursor_bo) { + unsigned attr[8]; + + attr[0] = KMS_BO_TYPE; + attr[1] = KMS_BO_TYPE_CURSOR; + attr[2] = KMS_WIDTH; + attr[3] = 64; + attr[4] = KMS_HEIGHT; + attr[5] = 64; + attr[6] = 0; + + if (kms_bo_create(ms->kms, attr, &crtcp->cursor_bo)) + return; + + if (kms_bo_get_prop(crtcp->cursor_bo, KMS_HANDLE, + &crtcp->cursor_handle)) + goto err_bo_destroy; + } + + kms_bo_map(crtcp->cursor_bo, (void**)&ptr); + memcpy(ptr, image, 64*64*4); + kms_bo_unmap(crtcp->cursor_bo); + + return; + +err_bo_destroy: + kms_bo_destroy(crtcp->cursor_bo); +} +#endif + +static void +crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) +{ + modesettingPtr ms = modesettingPTR(crtc->scrn); + if (ms->screen) + crtc_load_cursor_argb_ga3d(crtc, image); +#ifdef HAVE_LIBKMS + else if (ms->kms) + crtc_load_cursor_argb_kms(crtc, image); +#endif +} + static void crtc_show_cursor(xf86CrtcPtr crtc) { modesettingPtr ms = modesettingPTR(crtc->scrn); struct crtc_private *crtcp = crtc->driver_private; - if (crtcp->cursor_tex) + if (crtcp->cursor_tex || crtcp->cursor_bo) drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, crtcp->cursor_handle, 64, 64); } @@ -245,9 +301,14 @@ xorg_crtc_cursor_destroy(xf86CrtcPtr crtc) { struct crtc_private *crtcp = crtc->driver_private; - if (crtcp->cursor_tex) { + if (crtcp->cursor_tex) pipe_texture_reference(&crtcp->cursor_tex, NULL); - } +#ifdef HAVE_LIBKMS + if (crtcp->cursor_bo) + kms_bo_destroy(crtcp->cursor_bo); +#endif + + xfree(crtcp); } /* diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index bb8c2f744d2..c74fb280729 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -56,6 +56,10 @@ #include "xorg_tracker.h" #include "xorg_winsys.h" +#ifdef HAVE_LIBKMS +#include "libkms.h" +#endif + /* * Functions and symbols exported to Xorg via pointers. */ @@ -112,6 +116,7 @@ xorg_tracker_set_functions(ScrnInfoPtr scrn) * Internal function definitions */ +static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn); static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen); static Bool drv_save_hw_state(ScrnInfoPtr pScrn); static Bool drv_restore_hw_state(ScrnInfoPtr pScrn); @@ -152,75 +157,10 @@ drv_probe_ddc(ScrnInfoPtr pScrn, int index) ConfiguredMonitor = NULL; } -static Bool -drv_create_front_buffer(ScrnInfoPtr pScrn) -{ - modesettingPtr ms = modesettingPTR(pScrn); - unsigned handle, stride; - struct pipe_texture *tex; - - ms->noEvict = TRUE; - - tex = xorg_exa_create_root_texture(pScrn, pScrn->virtualX, pScrn->virtualY, - pScrn->depth, pScrn->bitsPerPixel); - - if (!tex) - return FALSE; - - if (!ms->api->local_handle_from_texture(ms->api, ms->screen, - tex, - &stride, - &handle)) - return FALSE; - - drmModeAddFB(ms->fd, - pScrn->virtualX, - pScrn->virtualY, - pScrn->depth, - pScrn->bitsPerPixel, - stride, - handle, - &ms->fb_id); - - pScrn->frameX0 = 0; - pScrn->frameY0 = 0; - drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - - pipe_texture_reference(&ms->root_texture, tex); - pipe_texture_reference(&tex, NULL); - return TRUE; -} - -static Bool -drv_bind_texture_to_root(ScrnInfoPtr pScrn) -{ - modesettingPtr ms = modesettingPTR(pScrn); - ScreenPtr pScreen = pScrn->pScreen; - struct pipe_texture *check; - PixmapPtr rootPixmap; - - rootPixmap = pScreen->GetScreenPixmap(pScreen); - - xorg_exa_set_displayed_usage(rootPixmap); - xorg_exa_set_shared_usage(rootPixmap); - xorg_exa_set_texture(rootPixmap, ms->root_texture); - if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL)) - FatalError("Couldn't adjust screen pixmap\n"); - - check = xorg_exa_get_texture(rootPixmap); - if (ms->root_texture != check) - FatalError("Created new root texture\n"); - - pipe_texture_reference(&check, NULL); - - return TRUE; -} - static Bool drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height) { modesettingPtr ms = modesettingPTR(pScrn); - unsigned handle, stride; PixmapPtr rootPixmap; ScreenPtr pScreen = pScrn->pScreen; @@ -234,36 +174,18 @@ drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height) * Remove the old framebuffer & texture. */ drmModeRmFB(ms->fd, ms->fb_id); - pipe_texture_reference(&ms->root_texture, NULL); - + if (!ms->destroy_front_buffer(pScrn)) + FatalError("failed to destroy front buffer\n"); rootPixmap = pScreen->GetScreenPixmap(pScreen); if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL)) return FALSE; - /* takes one ref */ - ms->root_texture = xorg_exa_get_texture(rootPixmap); - - if (!ms->api->local_handle_from_texture(ms->api, ms->screen, - ms->root_texture, - &stride, - &handle)) - FatalError("Could not get handle and stride from texture\n"); - - drmModeAddFB(ms->fd, - pScrn->virtualX, - pScrn->virtualY, - pScrn->depth, - pScrn->bitsPerPixel, - stride, - handle, - &ms->fb_id); - /* HW dependent - FIXME */ pScrn->displayWidth = pScrn->virtualX; /* now create new frontbuffer */ - return drv_create_front_buffer(pScrn) && drv_bind_texture_to_root(pScrn); + return ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn); } static const xf86CrtcConfigFuncsRec crtc_config_funcs = { @@ -291,13 +213,57 @@ drv_init_drm(ScrnInfoPtr pScrn) return FALSE; } - if (!ms->api) { - ms->api = drm_api_create(); + return TRUE; +} - if (!ms->api) - return FALSE; +static Bool +drv_init_resource_management(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + + if (ms->screen || ms->kms) + return TRUE; + + ms->api = drm_api_create(); + if (ms->api) { + ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL); + + if (ms->screen) + return TRUE; + + if (ms->api->destroy) + ms->api->destroy(ms->api); + + ms->api = NULL; } +#ifdef HAVE_LIBKMS + if (!kms_create(ms->fd, &ms->kms)) + return TRUE; +#endif + + return FALSE; +} + +static Bool +drv_close_resource_management(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + + if (ms->screen) + ms->screen->destroy(ms->screen); + ms->screen = NULL; + + if (ms->api && ms->api->destroy) + ms->api->destroy(ms->api); + ms->api = NULL; + +#ifdef HAVE_LIBKMS + if (ms->kms) + kms_destroy(ms->kms); + ms->kms = NULL; +#endif + return TRUE; } @@ -443,14 +409,16 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) xf86SetDpi(pScrn, 0, 0); /* Load the required sub modules */ - if (!xf86LoadSubModule(pScrn, "fb")) { + if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; - } - xf86LoadSubModule(pScrn, "exa"); + /* XXX: these aren't needed when we are using libkms */ + if (!xf86LoadSubModule(pScrn, "exa")) + return FALSE; #ifdef DRI2 - xf86LoadSubModule(pScrn, "dri2"); + if (!xf86LoadSubModule(pScrn, "dri2")) + return FALSE; #endif return TRUE; @@ -482,7 +450,8 @@ static void drv_block_handler(int i, pointer blockData, pointer pTimeout, pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); pScreen->BlockHandler = drv_block_handler; - ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, NULL); + if (ms->ctx) + ms->ctx->flush(ms->ctx, PIPE_FLUSH_RENDER_CACHE, NULL); #ifdef DRM_MODE_FEATURE_DIRTYFB { @@ -525,7 +494,7 @@ drv_create_screen_resources(ScreenPtr pScreen) ret = pScreen->CreateScreenResources(pScreen); pScreen->CreateScreenResources = drv_create_screen_resources; - drv_bind_texture_to_root(pScrn); + ms->bind_front_buffer(pScrn); ms->noEvict = FALSE; @@ -559,16 +528,19 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) modesettingPtr ms = modesettingPTR(pScrn); VisualPtr visual; - if (!drv_init_drm(pScrn)) + if (!drv_init_drm(pScrn)) { + FatalError("Could not init DRM"); return FALSE; + } - if (!ms->screen) { - ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL); + if (!drv_init_resource_management(pScrn)) { + FatalError("Could not init resource management (!pipe_screen && !libkms)"); + return FALSE; + } - if (!ms->screen) { - FatalError("Could not init pipe_screen\n"); - return FALSE; - } + if (!drv_init_front_buffer_functions(pScrn)) { + FatalError("Could not init front buffer manager"); + return FALSE; } pScrn->pScreen = pScreen; @@ -619,11 +591,16 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); - ms->exa = xorg_exa_init(pScrn, xf86ReturnOptValBool(ms->Options, - OPTION_2D_ACCEL, TRUE)); - ms->debug_fallback = debug_get_bool_option("XORG_DEBUG_FALLBACK", TRUE); + if (ms->screen) { + ms->exa = xorg_exa_init(pScrn, xf86ReturnOptValBool(ms->Options, + OPTION_2D_ACCEL, TRUE)); + ms->debug_fallback = debug_get_bool_option("XORG_DEBUG_FALLBACK", TRUE); - xorg_xv_init(pScreen); + xorg_xv_init(pScreen); +#ifdef DRI2 + xorg_dri2_init(pScreen); +#endif + } miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); @@ -655,10 +632,6 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); -#ifdef DRI2 - xorg_dri2_init(pScreen); -#endif - return drv_enter_vt(scrnIndex, 1); } @@ -745,10 +718,10 @@ drv_enter_vt(int scrnIndex, int flags) drv_save_hw_state(pScrn); } - if (!drv_create_front_buffer(pScrn)) + if (!ms->create_front_buffer(pScrn)) return FALSE; - if (!flags && !drv_bind_texture_to_root(pScrn)) + if (!flags && !ms->bind_front_buffer(pScrn)) return FALSE; if (!xf86SetDesiredModes(pScrn)) @@ -774,8 +747,10 @@ drv_close_screen(int scrnIndex, ScreenPtr pScreen) if (pScrn->vtSema) { drv_leave_vt(scrnIndex, 0); } + #ifdef DRI2 - xorg_dri2_close(pScreen); + if (ms->screen) + xorg_dri2_close(pScreen); #endif pScreen->BlockHandler = ms->blockHandler; @@ -789,14 +764,14 @@ drv_close_screen(int scrnIndex, ScreenPtr pScreen) } #endif - pipe_texture_reference(&ms->root_texture, NULL); + drmModeRmFB(ms->fd, ms->fb_id); + ms->destroy_front_buffer(pScrn); if (ms->exa) xorg_exa_close(pScrn); + ms->exa = NULL; - if (ms->api && ms->api->destroy) - ms->api->destroy(ms->api); - ms->api = NULL; + drv_close_resource_management(pScrn); drmClose(ms->fd); ms->fd = -1; @@ -812,4 +787,185 @@ drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) return MODE_OK; } + +/* + * Front buffer backing store functions. + */ + +static Bool +drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + pipe_texture_reference(&ms->root_texture, NULL); + return TRUE; +} + +static Bool +drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + unsigned handle, stride; + struct pipe_texture *tex; + + ms->noEvict = TRUE; + + tex = xorg_exa_create_root_texture(pScrn, pScrn->virtualX, pScrn->virtualY, + pScrn->depth, pScrn->bitsPerPixel); + + if (!tex) + return FALSE; + + if (!ms->api->local_handle_from_texture(ms->api, ms->screen, + tex, + &stride, + &handle)) + return FALSE; + + drmModeAddFB(ms->fd, + pScrn->virtualX, + pScrn->virtualY, + pScrn->depth, + pScrn->bitsPerPixel, + stride, + handle, + &ms->fb_id); + + pScrn->frameX0 = 0; + pScrn->frameY0 = 0; + drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + pipe_texture_reference(&ms->root_texture, tex); + pipe_texture_reference(&tex, NULL); + + return TRUE; +} + +static Bool +drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); + struct pipe_texture *check; + + xorg_exa_set_displayed_usage(rootPixmap); + xorg_exa_set_shared_usage(rootPixmap); + xorg_exa_set_texture(rootPixmap, ms->root_texture); + if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, NULL)) + FatalError("Couldn't adjust screen pixmap\n"); + + check = xorg_exa_get_texture(rootPixmap); + if (ms->root_texture != check) + FatalError("Created new root texture\n"); + + pipe_texture_reference(&check, NULL); + return TRUE; +} + +#ifdef HAVE_LIBKMS +static Bool +drv_destroy_front_buffer_kms(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + + if (!ms->root_bo) + return TRUE; + + kms_bo_unmap(ms->root_bo); + kms_bo_destroy(ms->root_bo); + ms->root_bo = NULL; + return TRUE; +} + +static Bool +drv_create_front_buffer_kms(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + unsigned handle, stride; + struct kms_bo *bo; + unsigned attr[8]; + + attr[0] = KMS_BO_TYPE; + attr[1] = KMS_BO_TYPE_SCANOUT; + attr[2] = KMS_WIDTH; + attr[3] = pScrn->virtualX; + attr[4] = KMS_HEIGHT; + attr[5] = pScrn->virtualY; + attr[6] = 0; + + if (kms_bo_create(ms->kms, attr, &bo)) + return FALSE; + + if (kms_bo_get_prop(bo, KMS_PITCH, &stride)) + goto err_destroy; + + if (kms_bo_get_prop(bo, KMS_HANDLE, &handle)) + goto err_destroy; + + drmModeAddFB(ms->fd, + pScrn->virtualX, + pScrn->virtualY, + pScrn->depth, + pScrn->bitsPerPixel, + stride, + handle, + &ms->fb_id); + + pScrn->frameX0 = 0; + pScrn->frameY0 = 0; + drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + ms->root_bo = bo; + + return TRUE; + +err_destroy: + kms_bo_destroy(bo); + return FALSE; +} + +static Bool +drv_bind_front_buffer_kms(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); + unsigned stride; + void *ptr; + + if (kms_bo_get_prop(ms->root_bo, KMS_PITCH, &stride)) + return FALSE; + + if (kms_bo_map(ms->root_bo, &ptr)) + return FALSE; + + pScreen->ModifyPixmapHeader(rootPixmap, + pScreen->width, + pScreen->height, + pScreen->rootDepth, + pScrn->bitsPerPixel, + stride, + ptr); + return TRUE; +} +#endif /* HAVE_LIBKMS */ + +static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + if (ms->screen) { + ms->destroy_front_buffer = drv_destroy_front_buffer_ga3d; + ms->create_front_buffer = drv_create_front_buffer_ga3d; + ms->bind_front_buffer = drv_bind_front_buffer_ga3d; +#ifdef HAVE_LIBKMS + } else if (ms->kms) { + ms->destroy_front_buffer = drv_destroy_front_buffer_kms; + ms->create_front_buffer = drv_create_front_buffer_kms; + ms->bind_front_buffer = drv_bind_front_buffer_kms; +#endif + } else + return FALSE; + + return TRUE; +} + /* vim: set sw=4 ts=8 sts=4: */ diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index 580dae474d3..31e11b48093 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -51,6 +51,8 @@ #define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg); +struct kms_bo; +struct kms_driver; struct exa_context; typedef struct @@ -86,6 +88,15 @@ typedef struct _modesettingRec void (*blockHandler)(int, pointer, pointer, pointer); CreateScreenResourcesProcPtr createScreenResources; + /* for frontbuffer backing store */ + Bool (*destroy_front_buffer)(ScrnInfoPtr pScrn); + Bool (*create_front_buffer)(ScrnInfoPtr pScrn); + Bool (*bind_front_buffer)(ScrnInfoPtr pScrn); + + /* kms */ + struct kms_driver *kms; + struct kms_bo *root_bo; + /* gallium */ struct drm_api *api; struct pipe_screen *screen; -- 2.30.2