X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fstate_trackers%2Fdri%2Fdrm%2Fdri2.c;h=0181588096defeff826bdddcd2f8107096d3702b;hb=94ccc31ba4f64ac480137fd90f1ded44d2072f6e;hp=c632f0fe4f365ca2c71c3b561a1d203747c441c5;hpb=feb619b7705897ca723e8fe728f739932f743327;p=mesa.git diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c index c632f0fe4f3..0181588096d 100644 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -33,13 +33,12 @@ #include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_debug.h" -#include "state_tracker/drm_api.h" +#include "state_tracker/drm_driver.h" #include "dri_screen.h" #include "dri_context.h" #include "dri_drawable.h" -#include "dri_st_api.h" -#include "dri2.h" +#include "dri2_buffer.h" /** * DRI2 flush extension. @@ -53,13 +52,13 @@ static void dri2_invalidate_drawable(__DRIdrawable *dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); - struct dri_context *ctx = dri_context(dPriv->driContextPriv); + struct dri_context *ctx = drawable->context; dri2InvalidateDrawable(dPriv); drawable->dPriv->lastStamp = *drawable->dPriv->pStamp; if (ctx) - ctx->st->notify_invalid_framebuffer(ctx->st, drawable->stfb); + ctx->st->notify_invalid_framebuffer(ctx->st, &drawable->base); } static const __DRI2flushExtension dri2FlushExtension = { @@ -68,68 +67,6 @@ static const __DRI2flushExtension dri2FlushExtension = { dri2_invalidate_drawable, }; -/** - * These are used for GLX_EXT_texture_from_pixmap - */ -static void -dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, - GLint format, __DRIdrawable *dPriv) -{ - struct dri_context *ctx = dri_context(pDRICtx); - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_texture *pt; - - dri_st_framebuffer_validate_att(drawable->stfb, ST_ATTACHMENT_FRONT_LEFT); - - pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; - - if (pt) { - ctx->st->teximage(ctx->st, - (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, - 0, drawable->stvis.color_format, pt, FALSE); - } -} - -static void -dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, - __DRIdrawable *dPriv) -{ - dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); -} - -static const __DRItexBufferExtension dri2TexBufferExtension = { - { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, - dri2_set_tex_buffer, - dri2_set_tex_buffer2, -}; - -/** - * Get the format of an attachment. - */ -static INLINE enum pipe_format -dri2_drawable_get_format(struct dri_drawable *drawable, - enum st_attachment_type statt) -{ - enum pipe_format format; - - switch (statt) { - case ST_ATTACHMENT_FRONT_LEFT: - case ST_ATTACHMENT_BACK_LEFT: - case ST_ATTACHMENT_FRONT_RIGHT: - case ST_ATTACHMENT_BACK_RIGHT: - format = drawable->stvis.color_format; - break; - case ST_ATTACHMENT_DEPTH_STENCIL: - format = drawable->stvis.depth_stencil_format; - break; - default: - format = PIPE_FORMAT_NONE; - break; - } - - return format; -} - /** * Retrieve __DRIbuffer from the DRI loader. */ @@ -157,9 +94,10 @@ dri2_drawable_get_buffers(struct dri_drawable *drawable, for (i = 0; i < *count; i++) { enum pipe_format format; + unsigned bind; int att, bpp; - format = dri2_drawable_get_format(drawable, statts[i]); + dri_drawable_get_format(drawable, statts[i], &format, &bind); if (format == PIPE_FORMAT_NONE) continue; @@ -235,7 +173,7 @@ dri2_drawable_get_buffers(struct dri_drawable *drawable, } /** - * Process __DRIbuffer and convert them into pipe_textures. + * Process __DRIbuffer and convert them into pipe_resources. */ static void dri2_drawable_process_buffers(struct dri_drawable *drawable, @@ -243,10 +181,10 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable, { struct dri_screen *screen = dri_screen(drawable->sPriv); __DRIdrawable *dri_drawable = drawable->dPriv; - struct pipe_texture templ; + struct pipe_resource templ; struct winsys_handle whandle; boolean have_depth = FALSE; - unsigned i; + unsigned i, bind; if (drawable->old_num == count && drawable->old_w == dri_drawable->w && @@ -255,15 +193,15 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable, return; for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_texture_reference(&drawable->textures[i], NULL); + pipe_resource_reference(&drawable->textures[i], NULL); memset(&templ, 0, sizeof(templ)); - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - templ.target = PIPE_TEXTURE_2D; + templ.target = screen->target; templ.last_level = 0; templ.width0 = dri_drawable->w; templ.height0 = dri_drawable->h; templ.depth0 = 1; + templ.array_size = 1; memset(&whandle, 0, sizeof(whandle)); @@ -302,16 +240,17 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable, break; } - format = dri2_drawable_get_format(drawable, statt); + dri_drawable_get_format(drawable, statt, &format, &bind); if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE) continue; templ.format = format; + templ.bind = bind; whandle.handle = buf->name; whandle.stride = buf->pitch; drawable->textures[statt] = - screen->pipe_screen->texture_from_handle(screen->pipe_screen, + screen->base.screen->resource_from_handle(screen->base.screen, &templ, &whandle); } @@ -321,11 +260,96 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable, memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); } +static __DRIbuffer * +dri2_allocate_buffer(__DRIscreen *sPriv, + unsigned attachment, unsigned format, + int width, int height) +{ + struct dri_screen *screen = dri_screen(sPriv); + struct dri2_buffer *buffer; + struct pipe_resource templ; + enum st_attachment_type statt; + enum pipe_format pf; + unsigned bind; + struct winsys_handle whandle; + + switch (attachment) { + case __DRI_BUFFER_FRONT_LEFT: + case __DRI_BUFFER_FAKE_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case __DRI_BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case __DRI_BUFFER_DEPTH: + case __DRI_BUFFER_DEPTH_STENCIL: + case __DRI_BUFFER_STENCIL: + statt = ST_ATTACHMENT_DEPTH_STENCIL; + bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ + break; + default: + statt = ST_ATTACHMENT_INVALID; + break; + } + + switch (format) { + case 32: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case 16: + pf = PIPE_FORMAT_Z16_UNORM; + break; + default: + return NULL; + } + + buffer = CALLOC_STRUCT(dri2_buffer); + if (!buffer) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = bind; + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + + buffer->resource = + screen->base.screen->resource_create(screen->base.screen, &templ); + if (!buffer->resource) + return NULL; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + screen->base.screen->resource_get_handle(screen->base.screen, + buffer->resource, &whandle); + + buffer->base.attachment = attachment; + buffer->base.name = whandle.handle; + buffer->base.cpp = util_format_get_blocksize(pf); + buffer->base.pitch = whandle.stride; + + return &buffer->base; +} + +static void +dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) +{ + struct dri2_buffer *buffer = dri2_buffer(bPriv); + + pipe_resource_reference(&buffer->resource, NULL); + FREE(buffer); +} + /* * Backend functions for st_framebuffer interface. */ -void +static void dri2_allocate_textures(struct dri_drawable *drawable, const enum st_attachment_type *statts, unsigned count) @@ -334,10 +358,11 @@ dri2_allocate_textures(struct dri_drawable *drawable, unsigned num_buffers = count; buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); - dri2_drawable_process_buffers(drawable, buffers, num_buffers); + if (buffers) + dri2_drawable_process_buffers(drawable, buffers, num_buffers); } -void +static void dri2_flush_frontbuffer(struct dri_drawable *drawable, enum st_attachment_type statt) { @@ -352,6 +377,198 @@ dri2_flush_frontbuffer(struct dri_drawable *drawable, } } +static __DRIimage * +dri2_lookup_egl_image(struct dri_screen *screen, void *handle) +{ + __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; + __DRIimage *img; + + if (!loader->lookupEGLImage) + return NULL; + + img = loader->lookupEGLImage(screen->sPriv, + handle, screen->sPriv->loaderPrivate); + + return img; +} + +static __DRIimage * +dri2_create_image_from_name(__DRIscreen *_screen, + int width, int height, int format, + int name, int pitch, void *loaderPrivate) +{ + struct dri_screen *screen = dri_screen(_screen); + __DRIimage *img; + struct pipe_resource templ; + struct winsys_handle whandle; + unsigned tex_usage; + enum pipe_format pf; + + tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + + switch (format) { + case __DRI_IMAGE_FORMAT_RGB565: + pf = PIPE_FORMAT_B5G6R5_UNORM; + break; + case __DRI_IMAGE_FORMAT_XRGB8888: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case __DRI_IMAGE_FORMAT_ARGB8888: + pf = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + default: + pf = PIPE_FORMAT_NONE; + break; + } + if (pf == PIPE_FORMAT_NONE) + return NULL; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = tex_usage; + templ.format = pf; + templ.target = screen->target; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + + memset(&whandle, 0, sizeof(whandle)); + whandle.handle = name; + whandle.stride = pitch * util_format_get_blocksize(pf); + + img->texture = screen->base.screen->resource_from_handle(screen->base.screen, + &templ, &whandle); + if (!img->texture) { + FREE(img); + return NULL; + } + + img->level = 0; + img->layer = 0; + img->loader_private = loaderPrivate; + + return img; +} + +static __DRIimage * +dri2_create_image_from_renderbuffer(__DRIcontext *context, + int renderbuffer, void *loaderPrivate) +{ + struct dri_context *ctx = dri_context(context); + + if (!ctx->st->get_resource_for_egl_image) + return NULL; + + /* TODO */ + return NULL; +} + +static __DRIimage * +dri2_create_image(__DRIscreen *_screen, + int width, int height, int format, + unsigned int use, void *loaderPrivate) +{ + struct dri_screen *screen = dri_screen(_screen); + __DRIimage *img; + struct pipe_resource templ; + unsigned tex_usage; + enum pipe_format pf; + + tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + + switch (format) { + case __DRI_IMAGE_FORMAT_RGB565: + pf = PIPE_FORMAT_B5G6R5_UNORM; + break; + case __DRI_IMAGE_FORMAT_XRGB8888: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case __DRI_IMAGE_FORMAT_ARGB8888: + pf = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + default: + pf = PIPE_FORMAT_NONE; + break; + } + if (pf == PIPE_FORMAT_NONE) + return NULL; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = tex_usage; + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + + img->texture = screen->base.screen->resource_create(screen->base.screen, &templ); + if (!img->texture) { + FREE(img); + return NULL; + } + + img->level = 0; + img->layer = 0; + + img->loader_private = loaderPrivate; + return img; +} + +static GLboolean +dri2_query_image(__DRIimage *image, int attrib, int *value) +{ + struct winsys_handle whandle; + memset(&whandle, 0, sizeof(whandle)); + + switch (attrib) { + case __DRI_IMAGE_ATTRIB_STRIDE: + image->texture->screen->resource_get_handle(image->texture->screen, + image->texture, &whandle); + *value = whandle.stride; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_HANDLE: + whandle.type = DRM_API_HANDLE_TYPE_KMS; + image->texture->screen->resource_get_handle(image->texture->screen, + image->texture, &whandle); + *value = whandle.handle; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_NAME: + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + image->texture->screen->resource_get_handle(image->texture->screen, + image->texture, &whandle); + *value = whandle.handle; + return GL_TRUE; + default: + return GL_FALSE; + } +} + +static void +dri2_destroy_image(__DRIimage *img) +{ + pipe_resource_reference(&img->texture, NULL); + FREE(img); +} + +static struct __DRIimageExtensionRec dri2ImageExtension = { + { __DRI_IMAGE, __DRI_IMAGE_VERSION }, + dri2_create_image_from_name, + dri2_create_image_from_renderbuffer, + dri2_destroy_image, + dri2_create_image, + dri2_query_image, +}; + /* * Backend function init_screen. */ @@ -360,43 +577,54 @@ static const __DRIextension *dri_screen_extensions[] = { &driReadDrawableExtension, &driCopySubBufferExtension.base, &driSwapControlExtension.base, - &driFrameTrackingExtension.base, &driMediaStreamCounterExtension.base, - &dri2TexBufferExtension.base, + &driTexBufferExtension.base, &dri2FlushExtension.base, + &dri2ImageExtension.base, + &dri2ConfigQueryExtension.base, NULL }; /** * This is the driver specific part of the createNewScreen entry point. * - * Returns the __GLcontextModes supported by this driver. + * Returns the struct gl_config supported by this driver. */ -const __DRIconfig ** +static const __DRIconfig ** dri2_init_screen(__DRIscreen * sPriv) { const __DRIconfig **configs; struct dri_screen *screen; - struct drm_create_screen_arg arg; + struct pipe_screen *pscreen; screen = CALLOC_STRUCT(dri_screen); if (!screen) return NULL; - screen->api = drm_api_create(); screen->sPriv = sPriv; screen->fd = sPriv->fd; sPriv->private = (void *)screen; sPriv->extensions = dri_screen_extensions; - arg.mode = DRM_CREATE_NORMAL; + pscreen = driver_descriptor.create_screen(screen->fd); + /* dri_init_screen_helper checks pscreen for us */ - configs = dri_init_screen_helper(screen, &arg, 32); + configs = dri_init_screen_helper(screen, pscreen, 32); if (!configs) goto fail; + sPriv->api_mask = 0; + if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK) + sPriv->api_mask |= 1 << __DRI_API_OPENGL; + if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK) + sPriv->api_mask |= 1 << __DRI_API_GLES; + if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK) + sPriv->api_mask |= 1 << __DRI_API_GLES2; + screen->auto_fake_front = dri_with_format(sPriv); + screen->broken_invalidate = !sPriv->dri2.useInvalidate; + screen->lookup_egl_image = dri2_lookup_egl_image; return configs; fail: @@ -405,6 +633,65 @@ fail: return NULL; } +static boolean +dri2_create_context(gl_api api, const struct gl_config * visual, + __DRIcontext * cPriv, void *sharedContextPrivate) +{ + struct dri_context *ctx = NULL; + + if (!dri_create_context(api, visual, cPriv, sharedContextPrivate)) + return FALSE; + + ctx = cPriv->driverPrivate; + + return TRUE; +} + +static boolean +dri2_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, boolean isPixmap) +{ + struct dri_drawable *drawable = NULL; + + if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) + return FALSE; + + drawable = dPriv->driverPrivate; + + drawable->allocate_textures = dri2_allocate_textures; + drawable->flush_frontbuffer = dri2_flush_frontbuffer; + + return TRUE; +} + +/** + * DRI driver virtual function table. + * + * DRI versions differ in their implementation of init_screen and swap_buffers. + */ +const struct __DriverAPIRec driDriverAPI = { + .InitScreen = NULL, + .InitScreen2 = dri2_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri2_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri2_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + + .GetSwapInfo = NULL, + .GetDrawableMSC = NULL, + .WaitForMSC = NULL, + + .SwapBuffers = NULL, + .CopySubBuffer = NULL, + + .AllocateBuffer = dri2_allocate_buffer, + .ReleaseBuffer = dri2_release_buffer, +}; + /* This is the table of extensions that the loader will dlsym() for. */ PUBLIC const __DRIextension *__driDriverExtensions[] = { &driCoreExtension.base,