| From d32913e3bb9ade8dbb739002bb239dd4e67546e2 Mon Sep 17 00:00:00 2001 |
| From: Frank Binns <frank.binns@imgtec.com> |
| Date: Mon, 30 Oct 2017 11:40:29 +0000 |
| Subject: [PATCH] dri/pvr: Introduce PowerVR DRI driver. |
| |
| Change-Id: Iab222336df40939dbc61807640f2fc8f26aca9b8 |
| --- |
| configure.ac | 8 + |
| src/mesa/drivers/dri/Makefile.am | 6 + |
| src/mesa/drivers/dri/pvr/Makefile.am | 49 ++ |
| src/mesa/drivers/dri/pvr/Makefile.sources | 35 + |
| src/mesa/drivers/dri/pvr/mesa_context.c | 259 +++++++ |
| src/mesa/drivers/dri/pvr/pvrdrawable.c | 660 +++++++++++++++++ |
| src/mesa/drivers/dri/pvr/pvrdri.c | 1134 +++++++++++++++++++++++++++++ |
| src/mesa/drivers/dri/pvr/pvrdri.h | 293 ++++++++ |
| src/mesa/drivers/dri/pvr/pvrext.c | 388 ++++++++++ |
| src/mesa/drivers/dri/pvr/pvrimage.c | 1042 ++++++++++++++++++++++++++ |
| src/mesa/drivers/dri/pvr/pvrimage.h | 93 +++ |
| src/mesa/drivers/dri/pvr/pvrmesa.h | 41 ++ |
| src/mesa/drivers/dri/pvr/pvrqueue.h | 74 ++ |
| src/mesa/drivers/dri/pvr/pvrutil.c | 589 +++++++++++++++ |
| 14 files changed, 4671 insertions(+) |
| create mode 100644 src/mesa/drivers/dri/pvr/Makefile.am |
| create mode 100644 src/mesa/drivers/dri/pvr/Makefile.sources |
| create mode 100644 src/mesa/drivers/dri/pvr/mesa_context.c |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrdrawable.c |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrdri.c |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrdri.h |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrext.c |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrimage.c |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrimage.h |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrmesa.h |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrqueue.h |
| create mode 100644 src/mesa/drivers/dri/pvr/pvrutil.c |
| |
| diff --git a/configure.ac b/configure.ac |
| index 7fade23..1117fbc 100644 |
| --- a/configure.ac |
| +++ b/configure.ac |
| @@ -76,6 +76,7 @@ LIBDRM_REQUIRED=2.4.75 |
| LIBDRM_RADEON_REQUIRED=2.4.71 |
| LIBDRM_AMDGPU_REQUIRED=2.4.82 |
| LIBDRM_INTEL_REQUIRED=2.4.75 |
| +LIBDRM_PVR_REQUIRED=2.4.60 |
| LIBDRM_NVVIEUX_REQUIRED=2.4.66 |
| LIBDRM_NOUVEAU_REQUIRED=2.4.66 |
| LIBDRM_FREEDRENO_REQUIRED=2.4.74 |
| @@ -1867,6 +1868,11 @@ if test -n "$with_dri_drivers"; then |
| HAVE_R200_DRI=yes |
| PKG_CHECK_MODULES([RADEON], [libdrm >= $LIBDRM_RADEON_REQUIRED libdrm_radeon >= $LIBDRM_RADEON_REQUIRED]) |
| ;; |
| + xpvr) |
| + HAVE_PVR_DRI=yes; |
| + PKG_CHECK_MODULES([PVR], [libdrm >= $LIBDRM_PVR_REQUIRED]) |
| + DRI_LIB_DEPS="$DRI_LIB_DEPS -lpvr_dri_support" |
| + ;; |
| xswrast) |
| HAVE_SWRAST_DRI=yes |
| ;; |
| @@ -2699,6 +2705,7 @@ AM_CONDITIONAL(HAVE_I965_DRI, test x$HAVE_I965_DRI = xyes) |
| AM_CONDITIONAL(HAVE_NOUVEAU_DRI, test x$HAVE_NOUVEAU_DRI = xyes) |
| AM_CONDITIONAL(HAVE_R200_DRI, test x$HAVE_R200_DRI = xyes) |
| AM_CONDITIONAL(HAVE_RADEON_DRI, test x$HAVE_RADEON_DRI = xyes) |
| +AM_CONDITIONAL(HAVE_PVR_DRI, test x$HAVE_PVR_DRI = xyes) |
| AM_CONDITIONAL(HAVE_SWRAST_DRI, test x$HAVE_SWRAST_DRI = xyes) |
| |
| AM_CONDITIONAL(HAVE_RADEON_VULKAN, test "x$HAVE_RADEON_VULKAN" = xyes) |
| @@ -2898,6 +2905,7 @@ AC_CONFIG_FILES([Makefile |
| src/mesa/drivers/dri/nouveau/Makefile |
| src/mesa/drivers/dri/r200/Makefile |
| src/mesa/drivers/dri/radeon/Makefile |
| + src/mesa/drivers/dri/pvr/Makefile |
| src/mesa/drivers/dri/swrast/Makefile |
| src/mesa/drivers/osmesa/Makefile |
| src/mesa/drivers/osmesa/osmesa.pc |
| diff --git a/src/mesa/drivers/dri/Makefile.am b/src/mesa/drivers/dri/Makefile.am |
| index 381c6a2..fa5cba5 100644 |
| --- a/src/mesa/drivers/dri/Makefile.am |
| +++ b/src/mesa/drivers/dri/Makefile.am |
| @@ -36,6 +36,12 @@ MEGADRIVERS_DEPS += radeon/libradeon_dri.la |
| MEGADRIVERS += radeon_dri.so |
| endif |
| |
| +if HAVE_PVR_DRI |
| +SUBDIRS += pvr |
| +MEGADRIVERS_DEPS += pvr/libpvr_dri.la |
| +MEGADRIVERS += pvr_dri.so |
| +endif |
| + |
| if HAVE_SWRAST_DRI |
| SUBDIRS += swrast |
| MEGADRIVERS_DEPS += swrast/libswrast_dri.la |
| diff --git a/src/mesa/drivers/dri/pvr/Makefile.am b/src/mesa/drivers/dri/pvr/Makefile.am |
| new file mode 100644 |
| index 0000000..23db505 |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/Makefile.am |
| @@ -0,0 +1,45 @@ |
| +# |
| +# Copyright (c) Imagination Technologies Ltd. |
| +# |
| +# The contents of this file are subject to the MIT license as set out below. |
| +# |
| +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| +# of this software and associated documentation files (the "Software"), to deal |
| +# in the Software without restriction, including without limitation the rights |
| +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| +# copies of the Software, and to permit persons to whom the Software is |
| +# furnished to do so, subject to the following conditions: |
| +# |
| +# The above copyright notice and this permission notice shall be included in |
| +# all copies or substantial portions of the Software. |
| +# |
| +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| +# THE SOFTWARE. |
| +# |
| + |
| +include Makefile.sources |
| + |
| +AM_CFLAGS = \ |
| + -I$(top_srcdir)/include \ |
| + -I$(top_srcdir)/src \ |
| + -I$(top_srcdir)/src/mapi \ |
| + -I$(top_srcdir)/src/mapi/glapi \ |
| + -I$(top_srcdir)/src/mesa \ |
| + -I$(top_srcdir)/src/mesa/main \ |
| + -I$(top_srcdir)/src/mesa/drivers/dri/common \ |
| + -I$(top_builddir)/src/mesa/main \ |
| + $(DEFINES) \ |
| + $(VISIBILITY_CFLAGS) \ |
| + $(PVR_CFLAGS) \ |
| + $(LIBDLOG_CFLAGS) |
| + |
| +AM_CXXFLAGS = $(AM_CFLAGS) |
| + |
| +noinst_LTLIBRARIES = libpvr_dri.la |
| +libpvr_dri_la_SOURCES = $(pvr_FILES) |
| +libpvr_dri_la_LIBADD = $(PVR_LIBS) $(LIBDLOG_LIBS) |
| diff --git a/src/mesa/drivers/dri/pvr/Makefile.sources b/src/mesa/drivers/dri/pvr/Makefile.sources |
| new file mode 100644 |
| index 0000000..c907dc0 |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/Makefile.sources |
| @@ -0,0 +1,35 @@ |
| +# |
| +# Copyright (c) Imagination Technologies Ltd. |
| +# |
| +# The contents of this file are subject to the MIT license as set out below. |
| +# |
| +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| +# of this software and associated documentation files (the "Software"), to deal |
| +# in the Software without restriction, including without limitation the rights |
| +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| +# copies of the Software, and to permit persons to whom the Software is |
| +# furnished to do so, subject to the following conditions: |
| +# |
| +# The above copyright notice and this permission notice shall be included in |
| +# all copies or substantial portions of the Software. |
| +# |
| +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| +# THE SOFTWARE. |
| +# |
| + |
| +pvr_INCLUDES = \ |
| + $(MESA_TOP)/src \ |
| + $(MESA_TOP)/src/mesa/drivers/dri/pvr |
| + |
| +pvr_FILES = \ |
| + mesa_context.c \ |
| + pvrdrawable.c \ |
| + pvrdri.c \ |
| + pvrext.c \ |
| + pvrimage.c \ |
| + pvrutil.c |
| diff --git a/src/mesa/drivers/dri/pvr/mesa_context.c b/src/mesa/drivers/dri/pvr/mesa_context.c |
| new file mode 100644 |
| index 0000000..bce441f |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/mesa_context.c |
| @@ -0,0 +1,259 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/** |
| + * \file context.c |
| + * Mesa context/visual/framebuffer management functions. |
| + * \author Brian Paul |
| + */ |
| + |
| +/* |
| + * Mesa 3-D graphics library |
| + * Version: 7.1 |
| + * |
| + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#include <stdlib.h> |
| +#include <dlfcn.h> |
| +#include <assert.h> |
| + |
| +#include "main/version.h" |
| + |
| +#include "imports.h" |
| +#include "dri_util.h" |
| +#include "glapi.h" |
| +#include "dispatch.h" |
| +#include "pvrmesa.h" |
| + |
| +#include "powervr/dri_support.h" |
| + |
| +/** |
| + * This is the default function we plug into all dispatch table slots |
| + * This helps prevents a segfault when someone calls a GL function without |
| + * first checking if the extension is supported. |
| + */ |
| +static int |
| +generic_nop(void) |
| +{ |
| + _mesa_warning(NULL, "User called no-op dispatch function (an unsupported extension function?)"); |
| + |
| + return 0; |
| +} |
| + |
| +/** |
| + * Allocate and initialise a new dispatch table. |
| + */ |
| +static struct _glapi_table * |
| +pvrdri_alloc_dispatch_table(void) |
| +{ |
| + unsigned numEntries = _glapi_get_dispatch_table_size(); |
| + _glapi_proc *table = malloc(numEntries * sizeof(_glapi_proc)); |
| + |
| + if (table) |
| + { |
| + unsigned i; |
| + |
| + for (i = 0; i < numEntries; i++) |
| + { |
| + table[i] = (_glapi_proc) generic_nop; |
| + } |
| + } |
| + |
| + return (struct _glapi_table *)table; |
| +} |
| + |
| +/** |
| + * Return a pointer to the pointer to the dispatch table of an API in PVRDRIScreen. |
| + */ |
| +static struct _glapi_table ** |
| +pvrdri_get_dispatch_table_ptr(PVRDRIScreen *psPVRScreen, PVRDRIAPIType eAPI) |
| +{ |
| + switch (eAPI) |
| + { |
| + case PVRDRI_API_GL: |
| + return &psPVRScreen->psPVROGLDispatch; |
| + break; |
| + case PVRDRI_API_GLES1: |
| + return &psPVRScreen->psOGLES1Dispatch; |
| + break; |
| + case PVRDRI_API_GLES2: |
| + return &psPVRScreen->psOGLES2Dispatch; |
| + break; |
| + default: |
| + return NULL; |
| + } |
| +} |
| + |
| +/** |
| + * Return a pointer to the dispatch table of an API in PVRDRIScreen. |
| + */ |
| +static struct _glapi_table * |
| +pvrdri_get_dispatch_table(PVRDRIScreen *psPVRScreen, PVRDRIAPIType eAPI) |
| +{ |
| + struct _glapi_table **ppsTable = pvrdri_get_dispatch_table_ptr(psPVRScreen, eAPI); |
| + |
| + return ppsTable ? *ppsTable : NULL; |
| +} |
| + |
| +/** |
| + * Free all dispatch tables. |
| + */ |
| +void |
| +pvrdri_free_dispatch_tables(PVRDRIScreen *psPVRScreen) |
| +{ |
| + if (psPVRScreen->psPVROGLDispatch != NULL) |
| + { |
| + free(psPVRScreen->psPVROGLDispatch); |
| + psPVRScreen->psPVROGLDispatch = NULL; |
| + } |
| + |
| + if (psPVRScreen->psOGLES1Dispatch != NULL) |
| + { |
| + free(psPVRScreen->psOGLES1Dispatch); |
| + psPVRScreen->psOGLES1Dispatch = NULL; |
| + } |
| + |
| + if (psPVRScreen->psOGLES2Dispatch != NULL) |
| + { |
| + free(psPVRScreen->psOGLES2Dispatch); |
| + psPVRScreen->psOGLES2Dispatch = NULL; |
| + } |
| +} |
| + |
| +static void |
| +pvrdri_add_mesa_dispatch(struct _glapi_table *psTable, |
| + PVRDRIAPIType eAPI, |
| + PVRDRIScreenImpl *psScreenImpl, |
| + void *pvLibHandle, |
| + const char *psFunc) |
| +{ |
| + int iOffset; |
| + const char *asFunc[] = {NULL, NULL}; |
| + _glapi_proc pfFunc; |
| + const char *error; |
| + |
| + (void) dlerror(); |
| + pfFunc = dlsym(pvLibHandle, psFunc); |
| + error = dlerror(); |
| + if (error != NULL) |
| + { |
| + pfFunc = PVRDRIEGLGetProcAddress(eAPI, psScreenImpl, psFunc); |
| + if (pfFunc == NULL) |
| + { |
| +#if 0 |
| + /* |
| + * Not all extensions are supported, so there may |
| + * be quite a lot of lookup failures. |
| + */ |
| + _mesa_warning(NULL, "Couldn't get address of %s", psFunc); |
| +#endif |
| + return; |
| + } |
| + } |
| + |
| + asFunc[0] = psFunc; |
| + iOffset = _glapi_add_dispatch(asFunc, ""); |
| + if (iOffset == -1) |
| + { |
| + _mesa_warning(NULL, "Couldn't add %s to the Mesa dispatch table", psFunc); |
| + } |
| + else |
| + { |
| + SET_by_offset(psTable, iOffset, pfFunc); |
| + } |
| +} |
| + |
| +static void |
| +pvrdri_set_mesa_dispatch(struct _glapi_table *psTable, |
| + PVRDRIAPIType eAPI, |
| + PVRDRIScreenImpl *psScreenImpl, |
| + void *pvLibHandle, |
| + unsigned uNumFuncs) |
| +{ |
| + unsigned i; |
| + |
| + for (i = 0; i < uNumFuncs; i++) |
| + { |
| + const char *psFunc = PVRDRIGetAPIFunc(eAPI, i); |
| + |
| + assert(psFunc); |
| + |
| + pvrdri_add_mesa_dispatch(psTable, |
| + eAPI, |
| + psScreenImpl, |
| + pvLibHandle, |
| + psFunc); |
| + } |
| +} |
| + |
| +bool |
| +pvrdri_create_dispatch_table(PVRDRIScreen *psPVRScreen, PVRDRIAPIType eAPI) |
| +{ |
| + PVRDRIScreenImpl *psScreenImpl = psPVRScreen->psImpl; |
| + struct _glapi_table **ppsTable = pvrdri_get_dispatch_table_ptr(psPVRScreen, eAPI); |
| + void *pvLibHandle; |
| + unsigned uNumFuncs; |
| + |
| + if (ppsTable == NULL) |
| + { |
| + return false; |
| + } |
| + |
| + if (*ppsTable != NULL) |
| + { |
| + return true; |
| + } |
| + |
| + pvLibHandle = PVRDRIEGLGetLibHandle(eAPI, psScreenImpl);; |
| + uNumFuncs = PVRDRIGetNumAPIFuncs(eAPI); |
| + if (!pvLibHandle || !uNumFuncs) |
| + { |
| + return false; |
| + } |
| + |
| + *ppsTable = pvrdri_alloc_dispatch_table(); |
| + if (*ppsTable == NULL) |
| + { |
| + return false; |
| + } |
| + |
| + pvrdri_set_mesa_dispatch(*ppsTable, |
| + eAPI, |
| + psScreenImpl, |
| + pvLibHandle, |
| + uNumFuncs); |
| + |
| + return true; |
| +} |
| + |
| +void |
| +pvrdri_set_null_dispatch_table(void) |
| +{ |
| + _glapi_set_dispatch(NULL); |
| +} |
| + |
| +void |
| +pvrdri_set_dispatch_table(PVRDRIContext *psPVRContext) |
| +{ |
| + struct _glapi_table *psTable = pvrdri_get_dispatch_table(psPVRContext->psPVRScreen, psPVRContext->eAPI); |
| + |
| + _glapi_set_dispatch(psTable); |
| +} |
| diff --git a/src/mesa/drivers/dri/pvr/pvrdrawable.c b/src/mesa/drivers/dri/pvr/pvrdrawable.c |
| new file mode 100644 |
| index 0000000..044097e |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrdrawable.c |
| @@ -0,0 +1,660 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/* |
| + * Copyright (c) Imagination Technologies Ltd. |
| + * |
| + * The contents of this file are subject to the MIT license as set out below. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#include <assert.h> |
| + |
| +#include "dri_util.h" |
| + |
| +#include "pvrdri.h" |
| +#include "pvrimage.h" |
| + |
| +static PVRDRIBufferImpl *PVRGetBackingBuffer(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRDRIBuffer *psPVRBuffer = &psPVRDrawable->sPVRBuffer; |
| + |
| + if (psPVRDrawable->psPVRScreen->psDRIScreen->image.loader) |
| + { |
| + return PVRDRIImageGetSharedBuffer(psPVRBuffer->uBacking.sImage.psImage); |
| + } |
| + else |
| + { |
| + return psPVRBuffer->uBacking.sDRI2.psBuffer; |
| + } |
| +} |
| + |
| +static inline void PVRDRIMarkAllRenderSurfacesAsInvalid(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRQElem *psQElem = psPVRDrawable->sPVRContextHead.pvForw; |
| + |
| + while (psQElem != &psPVRDrawable->sPVRContextHead) |
| + { |
| + PVRDRIContext *psPVRContext = PVRQ_CONTAINER_OF(psQElem, PVRDRIContext, sQElem); |
| + PVRDRIEGLMarkRendersurfaceInvalid(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl); |
| + psQElem = psPVRContext->sQElem.pvForw; |
| + } |
| + |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + PVR drawable local functions (image driver loader) |
| +*/ /**************************************************************************/ |
| + |
| +static inline void PVRDrawableImageDestroy(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRDRIBuffer *psPVRBuffer = &psPVRDrawable->sPVRBuffer; |
| + |
| + if (psPVRBuffer->uBacking.sImage.psImage) |
| + { |
| + PVRDRIUnrefImage(psPVRBuffer->uBacking.sImage.psImage); |
| + psPVRBuffer->uBacking.sImage.psImage = NULL; |
| + } |
| +} |
| + |
| +static void PVRDrawableImageUpdate(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRDRIBuffer *psPVRBuffer = &psPVRDrawable->sPVRBuffer; |
| + __DRIimage *psImage = psPVRDrawable->uDRI.sImage.psDRI; |
| + |
| + if (psPVRBuffer->uBacking.sImage.psImage != psImage) |
| + { |
| + assert(PVRDRIImageGetSharedBuffer(psImage) != NULL); |
| + |
| + PVRDRIRefImage(psImage); |
| + |
| + PVRDrawableImageDestroy(psPVRDrawable); |
| + |
| + psPVRBuffer->uBacking.sImage.psImage = psImage; |
| + |
| + } |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + Function Name : PVRImageDrawableGetNativeInfo |
| + Inputs : psPVRDrawable |
| + Returns : Boolean |
| + Description : Update native drawable information. |
| +*/ /**************************************************************************/ |
| +static bool PVRImageDrawableGetNativeInfo(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + __DRIdrawable *psDRIDrawable = psPVRDrawable->psDRIDrawable; |
| + __DRIscreen *psDRIScreen = psPVRDrawable->psPVRScreen->psDRIScreen; |
| + struct __DRIimageList sImages; |
| + uint32_t uiBufferMask; |
| + const PVRDRIImageFormat *psFormat; |
| + |
| + assert(psDRIScreen->image.loader != NULL); |
| + assert(psDRIScreen->image.loader->getBuffers); |
| + |
| + psFormat = PVRDRIIMGPixelFormatToImageFormat(psPVRDrawable->ePixelFormat); |
| + if (!psFormat) |
| + { |
| + errorMessage("%s: Unsupported format (format = %u)\n", |
| + __func__, psPVRDrawable->ePixelFormat); |
| + return false; |
| + } |
| + |
| + uiBufferMask = psPVRDrawable->bDoubleBuffered ? |
| + __DRI_IMAGE_BUFFER_BACK : |
| + __DRI_IMAGE_BUFFER_FRONT; |
| + |
| + if (!psDRIScreen->image.loader->getBuffers(psDRIDrawable, |
| + psFormat->iDRIFormat, |
| + NULL, |
| + psDRIDrawable->loaderPrivate, |
| + uiBufferMask, |
| + &sImages)) |
| + { |
| + errorMessage("%s: Image get buffers call failed\n", __func__); |
| + return false; |
| + } |
| + |
| + psPVRDrawable->uDRI.sImage.psDRI = |
| + (sImages.image_mask & __DRI_IMAGE_BUFFER_BACK) ? |
| + sImages.back : sImages.front; |
| + |
| + return true; |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + Function Name : PVRImageDrawableCreate |
| + Inputs : psPVRDrawable |
| + Returns : Boolean |
| + Description : Create drawable |
| +*/ /**************************************************************************/ |
| +static bool PVRImageDrawableCreate(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + __DRIdrawable *psDRIDrawable = psPVRDrawable->psDRIDrawable; |
| + uint32_t uBytesPerPixel; |
| + PVRDRIBufferAttribs sBufferAttribs; |
| + |
| + if (!PVRImageDrawableGetNativeInfo(psPVRDrawable)) |
| + { |
| + return false; |
| + } |
| + |
| + PVRDRIEGLImageGetAttribs( |
| + PVRDRIImageGetEGLImage(psPVRDrawable->uDRI.sImage.psDRI), |
| + &sBufferAttribs); |
| + uBytesPerPixel = PVRDRIPixFmtGetBlockSize(sBufferAttribs.ePixFormat); |
| + |
| + psDRIDrawable->w = sBufferAttribs.uiWidth; |
| + psDRIDrawable->h = sBufferAttribs.uiHeight; |
| + psPVRDrawable->uStride = sBufferAttribs.uiStrideInBytes; |
| + psPVRDrawable->uBytesPerPixel = uBytesPerPixel; |
| + |
| + PVRDrawableImageUpdate(psPVRDrawable); |
| + |
| + if (!PVREGLDrawableCreate(psPVRDrawable->psPVRScreen->psImpl, |
| + psPVRDrawable->psImpl)) |
| + { |
| + errorMessage("%s: Couldn't create EGL drawable\n", __func__); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + Function Name : PVRImageDrawableUpdate |
| + Inputs : psPVRDrawable |
| + Returns : Boolean |
| + Description : Update drawable |
| +*/ /**************************************************************************/ |
| +static bool PVRImageDrawableUpdate(PVRDRIDrawable *psPVRDrawable, |
| + bool bAllowRecreate) |
| +{ |
| + __DRIdrawable *psDRIDrawable = psPVRDrawable->psDRIDrawable; |
| + PVRDRIBuffer *psPVRBuffer = &psPVRDrawable->sPVRBuffer; |
| + uint32_t uBytesPerPixel; |
| + PVRDRIBufferAttribs sBufferAttribs; |
| + bool bRecreate; |
| + |
| + PVRDRIEGLImageGetAttribs( |
| + PVRDRIImageGetEGLImage(psPVRDrawable->uDRI.sImage.psDRI), |
| + &sBufferAttribs); |
| + uBytesPerPixel = PVRDRIPixFmtGetBlockSize(sBufferAttribs.ePixFormat); |
| + |
| + bRecreate = (!psPVRDrawable->bDoubleBuffered && |
| + psPVRBuffer->uBacking.sImage.psImage != |
| + psPVRDrawable->uDRI.sImage.psDRI) || |
| + (psDRIDrawable->w != sBufferAttribs.uiWidth) || |
| + (psDRIDrawable->h != sBufferAttribs.uiHeight) || |
| + (psPVRDrawable->uStride != |
| + sBufferAttribs.uiStrideInBytes) || |
| + (psPVRDrawable->uBytesPerPixel != uBytesPerPixel); |
| + |
| + if (bRecreate) |
| + { |
| + if (bAllowRecreate) |
| + { |
| + PVRDRIMarkAllRenderSurfacesAsInvalid(psPVRDrawable); |
| + |
| + psDRIDrawable->w = sBufferAttribs.uiWidth; |
| + psDRIDrawable->h = sBufferAttribs.uiHeight; |
| + psPVRDrawable->uStride = sBufferAttribs.uiStrideInBytes; |
| + psPVRDrawable->uBytesPerPixel = uBytesPerPixel; |
| + } |
| + else |
| + { |
| + return false; |
| + } |
| + } |
| + |
| + PVRDrawableImageUpdate(psPVRDrawable); |
| + |
| + if (bRecreate) |
| + { |
| + if (!PVREGLDrawableRecreate(psPVRDrawable->psPVRScreen->psImpl, |
| + psPVRDrawable->psImpl)) |
| + { |
| + errorMessage("%s: Couldn't recreate EGL drawable\n", |
| + __func__); |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + PVR drawable local functions (DRI2 loader) |
| +*/ /**************************************************************************/ |
| + |
| +static inline void PVRDrawableDRI2BufferDestroy(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRDRIBuffer *psPVRBuffer = &psPVRDrawable->sPVRBuffer; |
| + |
| + if (psPVRBuffer->uBacking.sDRI2.psBuffer) |
| + { |
| + PVRDRIBufferDestroy(psPVRBuffer->uBacking.sDRI2.psBuffer); |
| + psPVRBuffer->uBacking.sDRI2.psBuffer = NULL; |
| + } |
| +} |
| + |
| +static bool PVRDrawableDRI2BufferUpdate(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + __DRIdrawable *psDRIDrawable = psPVRDrawable->psDRIDrawable; |
| + PVRDRIScreen *psPVRScreen = psPVRDrawable->psPVRScreen; |
| + PVRDRIBuffer *psPVRBuffer = &psPVRDrawable->sPVRBuffer; |
| + __DRIbuffer *psDRIBuffer = &psPVRDrawable->uDRI.sBuffer.sDRI; |
| + |
| + if (psPVRBuffer->uBacking.sDRI2.uiName != psDRIBuffer->name) |
| + { |
| + PVRDRIBufferImpl *psBuffer; |
| + |
| + if (PVRDRIPixFmtGetBlockSize(psPVRDrawable->ePixelFormat) != |
| + psDRIBuffer->cpp) |
| + { |
| + errorMessage("%s: DRI buffer format doesn't match drawable format\n", __func__); |
| + return false; |
| + } |
| + |
| + psBuffer = PVRDRIBufferCreateFromName(psPVRScreen->psImpl, |
| + psDRIBuffer->name, |
| + psDRIDrawable->w, |
| + psDRIDrawable->h, |
| + psDRIBuffer->pitch, |
| + 0); |
| + if (!psBuffer) |
| + { |
| + errorMessage("%s: Failed to create buffer\n", __func__); |
| + return false; |
| + } |
| + |
| + PVRDrawableDRI2BufferDestroy(psPVRDrawable); |
| + |
| + psPVRBuffer->uBacking.sDRI2.psBuffer = psBuffer; |
| + psPVRBuffer->uBacking.sDRI2.uiName = psDRIBuffer->name; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +/*********************************************************************************** |
| + Function Name : PVRDRI2DrawableGetNativeInfo |
| + Inputs : psPVRDrawable |
| + Returns : Boolean |
| + Description : Update native drawable information. |
| +************************************************************************************/ |
| +static bool PVRDRI2DrawableGetNativeInfo(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + __DRIdrawable *psDRIDrawable = psPVRDrawable->psDRIDrawable; |
| + __DRIscreen *psDRIScreen = psPVRDrawable->psPVRScreen->psDRIScreen; |
| + unsigned int auiAttachmentReq[2]; |
| + __DRIbuffer *psDRIBuffers; |
| + int iBufCount; |
| + int i; |
| + int w, h; |
| + |
| + assert(psDRIScreen->dri2.loader); |
| + assert(psDRIScreen->dri2.loader->getBuffersWithFormat); |
| + |
| + if (psPVRDrawable->bDoubleBuffered) |
| + { |
| + auiAttachmentReq[0] = __DRI_BUFFER_BACK_LEFT; |
| + } |
| + else |
| + { |
| + auiAttachmentReq[0] = __DRI_BUFFER_FRONT_LEFT; |
| + } |
| + |
| + auiAttachmentReq[1] = PVRDRIPixFmtGetDepth(psPVRDrawable->ePixelFormat); |
| + |
| + /* Do not free psDRIBuffers when finished with it */ |
| + psDRIBuffers = psDRIScreen->dri2.loader->getBuffersWithFormat(psDRIDrawable, |
| + &w, |
| + &h, |
| + &auiAttachmentReq[0], |
| + 1, |
| + &iBufCount, |
| + psDRIDrawable->loaderPrivate); |
| + if (psDRIBuffers == NULL) |
| + { |
| + errorMessage("%s: DRI2 get buffers call failed\n", __func__); |
| + return false; |
| + } |
| + |
| + for (i = 0; i < iBufCount; i++) |
| + { |
| + if (psDRIBuffers[i].attachment == auiAttachmentReq[0] || |
| + (psDRIBuffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT && |
| + auiAttachmentReq[0] == __DRI_BUFFER_FRONT_LEFT)) |
| + { |
| + break; |
| + } |
| + } |
| + |
| + if (i == iBufCount) |
| + { |
| + errorMessage("%s: Couldn't get DRI buffer information\n", __func__); |
| + return false; |
| + } |
| + |
| + psPVRDrawable->uDRI.sBuffer.sDRI = psDRIBuffers[i]; |
| + psPVRDrawable->uDRI.sBuffer.w = w; |
| + psPVRDrawable->uDRI.sBuffer.h = h; |
| + |
| + return true; |
| +} |
| + |
| +/*********************************************************************************** |
| + Function Name : PVRDRI2DrawableCreate |
| + Inputs : psPVRDrawable |
| + Returns : Boolean |
| + Description : Create drawable. |
| +************************************************************************************/ |
| +static bool PVRDRI2DrawableCreate(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + __DRIdrawable *psDRIDrawable = psPVRDrawable->psDRIDrawable; |
| + |
| + if (!PVRDRI2DrawableGetNativeInfo(psPVRDrawable)) |
| + { |
| + return false; |
| + } |
| + |
| + psDRIDrawable->w = psPVRDrawable->uDRI.sBuffer.w; |
| + psDRIDrawable->h = psPVRDrawable->uDRI.sBuffer.h; |
| + psPVRDrawable->uStride = psPVRDrawable->uDRI.sBuffer.sDRI.pitch; |
| + psPVRDrawable->uBytesPerPixel = psPVRDrawable->uDRI.sBuffer.sDRI.cpp; |
| + |
| + if (!PVRDrawableDRI2BufferUpdate(psPVRDrawable)) |
| + { |
| + errorMessage("%s: Couldn't set drawable buffer\n", __func__); |
| + return false; |
| + } |
| + |
| + if (!PVREGLDrawableCreate(psPVRDrawable->psPVRScreen->psImpl, |
| + psPVRDrawable->psImpl)) |
| + { |
| + errorMessage("%s: Couldn't create EGL drawable\n", __func__); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +/*********************************************************************************** |
| + Function Name : PVRDRI2DrawableUpdate |
| + Inputs : psPVRDrawable |
| + Returns : Boolean |
| + Description : Update drawable |
| +************************************************************************************/ |
| +static bool PVRDRI2DrawableUpdate(PVRDRIDrawable *psPVRDrawable, |
| + bool bAllowRecreate) |
| +{ |
| + __DRIdrawable *psDRIDrawable = psPVRDrawable->psDRIDrawable; |
| + PVRDRIBuffer *psPVRBuffer = &psPVRDrawable->sPVRBuffer; |
| + bool bRecreate; |
| + |
| + /* |
| + * If we're single buffered, check the current buffer name against |
| + * the new buffer name, otherwise don't, as the name will change as |
| + * part of swap buffers. |
| + */ |
| + |
| + bRecreate = (!psPVRDrawable->bDoubleBuffered && |
| + psPVRBuffer->uBacking.sDRI2.uiName != |
| + psPVRDrawable->uDRI.sBuffer.sDRI.name) || |
| + (psDRIDrawable->w != psPVRDrawable->uDRI.sBuffer.w) || |
| + (psDRIDrawable->h != psPVRDrawable->uDRI.sBuffer.h) || |
| + (psPVRDrawable->uStride != |
| + psPVRDrawable->uDRI.sBuffer.sDRI.pitch) || |
| + (psPVRDrawable->uBytesPerPixel != |
| + psPVRDrawable->uDRI.sBuffer.sDRI.cpp); |
| + |
| + if (bRecreate) |
| + { |
| + if (bAllowRecreate) |
| + { |
| + PVRDRIMarkAllRenderSurfacesAsInvalid(psPVRDrawable); |
| + |
| + psDRIDrawable->w = psPVRDrawable->uDRI.sBuffer.w; |
| + psDRIDrawable->h = psPVRDrawable->uDRI.sBuffer.h; |
| + psPVRDrawable->uStride = |
| + psPVRDrawable->uDRI.sBuffer.sDRI.pitch; |
| + psPVRDrawable->uBytesPerPixel = |
| + psPVRDrawable->uDRI.sBuffer.sDRI.cpp; |
| + } |
| + else |
| + { |
| + return false; |
| + } |
| + } |
| + |
| + if (!PVRDrawableDRI2BufferUpdate(psPVRDrawable)) |
| + { |
| + errorMessage("%s: Couldn't update drawable buffer\n", |
| + __func__); |
| + return false; |
| + } |
| + |
| + if (bRecreate) |
| + { |
| + if (!PVREGLDrawableRecreate(psPVRDrawable->psPVRScreen->psImpl, |
| + psPVRDrawable->psImpl)) |
| + { |
| + errorMessage("%s: Couldn't recreate EGL drawable\n", |
| + __func__); |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + PVR drawable local functions |
| +*/ /**************************************************************************/ |
| + |
| +/*********************************************************************************** |
| + Function Name : PVRDRIDrawableUpdateNativeInfo |
| + Inputs : psPVRDrawable |
| + Description : Update native drawable information. |
| +************************************************************************************/ |
| +bool PVRDRIDrawableUpdateNativeInfo(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + return (psPVRDrawable->psPVRScreen->psDRIScreen->image.loader) ? |
| + PVRImageDrawableGetNativeInfo(psPVRDrawable) : |
| + PVRDRI2DrawableGetNativeInfo(psPVRDrawable); |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + Function Name : PVRDRIDrawableUpdate |
| + Inputs : psPVRDrawable |
| + Description : Update drawable |
| +*/ /**************************************************************************/ |
| +static bool PVRDRIDrawableUpdate(PVRDRIDrawable *psPVRDrawable, |
| + bool bAllowRecreate) |
| +{ |
| + bool bRes = true; |
| + |
| + PVRDRIDrawableLock(psPVRDrawable); |
| + |
| + if (psPVRDrawable->bDrawableUpdating) |
| + { |
| + bRes = false; |
| + goto Exit; |
| + } |
| + psPVRDrawable->bDrawableUpdating = true; |
| + |
| + if (psPVRDrawable->psPVRScreen->bUseInvalidate) |
| + { |
| + if (!psPVRDrawable->bDrawableInfoInvalid) |
| + { |
| + bRes = true; |
| + goto ExitNotUpdating; |
| + } |
| + } |
| + |
| + if (!psPVRDrawable->bDrawableInfoUpdated) |
| + { |
| + if (!PVRDRIDrawableUpdateNativeInfo(psPVRDrawable)) |
| + { |
| + bRes = false; |
| + goto ExitNotUpdating; |
| + } |
| + psPVRDrawable->bDrawableInfoUpdated = true; |
| + } |
| + |
| + if (psPVRDrawable->psPVRScreen->psDRIScreen->image.loader) |
| + { |
| + bRes = PVRImageDrawableUpdate(psPVRDrawable, bAllowRecreate); |
| + } |
| + else |
| + { |
| + bRes = PVRDRI2DrawableUpdate(psPVRDrawable, bAllowRecreate); |
| + } |
| + |
| + if (bRes) |
| + { |
| + psPVRDrawable->bDrawableInfoUpdated = false; |
| + psPVRDrawable->bDrawableInfoInvalid = false; |
| + } |
| + |
| +ExitNotUpdating: |
| + psPVRDrawable->bDrawableUpdating = false; |
| +Exit: |
| + PVRDRIDrawableUnlock(psPVRDrawable); |
| + |
| + return bRes; |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + Function Name : PVRDRIDrawableRecreate |
| + Inputs : psPVRDrawable |
| + Description : Recreate drawable |
| +*/ /**************************************************************************/ |
| +bool PVRDRIDrawableRecreate(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + return PVRDRIDrawableUpdate(psPVRDrawable, true); |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + Function Name : PVRDRIDrawableCreate |
| + Inputs : psPVRDrawable |
| + Description : Create drawable |
| +*/ /**************************************************************************/ |
| +static bool PVRDRIDrawableCreate(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + bool bRes; |
| + |
| + if (psPVRDrawable->psPVRScreen->psDRIScreen->image.loader) |
| + { |
| + bRes = PVRImageDrawableCreate(psPVRDrawable); |
| + } |
| + else |
| + { |
| + bRes = PVRDRI2DrawableCreate(psPVRDrawable); |
| + } |
| + |
| + return bRes; |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + PVR drawable interface |
| +*/ /**************************************************************************/ |
| +bool PVRDRIDrawableInit(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + if (psPVRDrawable->bInitialised) |
| + { |
| + return true; |
| + } |
| + |
| + if (!PVRDRIDrawableCreate(psPVRDrawable)) |
| + { |
| + return false; |
| + } |
| + |
| + psPVRDrawable->bInitialised = true; |
| + |
| + return true; |
| +} |
| + |
| +void PVRDRIDrawableDeinit(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + (void) PVREGLDrawableDestroy(psPVRDrawable->psPVRScreen->psImpl, |
| + psPVRDrawable->psImpl); |
| + |
| + if (psPVRDrawable->psPVRScreen->psDRIScreen->image.loader) |
| + { |
| + PVRDrawableImageDestroy(psPVRDrawable); |
| + } |
| + else |
| + { |
| + PVRDrawableDRI2BufferDestroy(psPVRDrawable); |
| + } |
| + |
| + psPVRDrawable->bInitialised = false; |
| +} |
| + |
| +bool PVRDRIDrawableGetParameters(PVRDRIDrawable *psPVRDrawable, |
| + PVRDRIBufferImpl **ppsDstBuffer, |
| + PVRDRIBufferImpl **ppsAccumBuffer, |
| + PVRDRIBufferAttribs *psAttribs, |
| + bool *pbDoubleBuffered) |
| +{ |
| + __DRIdrawable *psDRIDrawable = psPVRDrawable->psDRIDrawable; |
| + |
| + if (ppsDstBuffer || ppsAccumBuffer) |
| + { |
| + PVRDRIBufferImpl *psDstBuffer; |
| + |
| + psDstBuffer = PVRGetBackingBuffer(psPVRDrawable); |
| + if (!psDstBuffer) |
| + { |
| + errorMessage("%s: Couldn't get backing buffer\n", |
| + __func__); |
| + return false; |
| + } |
| + |
| + if (ppsDstBuffer) |
| + { |
| + *ppsDstBuffer = psDstBuffer; |
| + } |
| + |
| + if (ppsAccumBuffer) |
| + { |
| + *ppsAccumBuffer = psDstBuffer; |
| + } |
| + } |
| + |
| + if (psAttribs) |
| + { |
| + psAttribs->uiWidth = psDRIDrawable->w; |
| + psAttribs->uiHeight = psDRIDrawable->h; |
| + psAttribs->ePixFormat = psPVRDrawable->ePixelFormat; |
| + psAttribs->uiStrideInBytes = psPVRDrawable->uStride; |
| + } |
| + |
| + if (pbDoubleBuffered) |
| + { |
| + *pbDoubleBuffered = psPVRDrawable->bDoubleBuffered; |
| + } |
| + |
| + return true; |
| +} |
| diff --git a/src/mesa/drivers/dri/pvr/pvrdri.c b/src/mesa/drivers/dri/pvr/pvrdri.c |
| new file mode 100644 |
| index 0000000..9ac7e45 |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrdri.c |
| @@ -0,0 +1,1134 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/* |
| + * Copyright (c) Imagination Technologies Ltd. |
| + * |
| + * The contents of this file are subject to the MIT license as set out below. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#include <assert.h> |
| +#include <pthread.h> |
| +#include <string.h> |
| +#include <xf86drm.h> |
| + |
| +#include "EGL/egl.h" |
| +#include "EGL/eglext.h" |
| + |
| +#include "dri_util.h" |
| + |
| +#include "pvrdri.h" |
| +#include "pvrimage.h" |
| + |
| +#include "pvrmesa.h" |
| + |
| +#define PVR_IMAGE_LOADER_VER_MIN 1 |
| +#define PVR_DRI2_LOADER_VER_MIN 3 |
| + |
| +#define PVRDRI_FLUSH_WAIT_FOR_HW (1U << 0) |
| +#define PVRDRI_FLUSH_NEW_EXTERNAL_FRAME (1U << 1) |
| +#define PVRDRI_FLUSH_ALL_SURFACES (1U << 2) |
| + |
| +typedef struct PVRBufferRec |
| +{ |
| + __DRIbuffer sDRIBuffer; |
| + PVRDRIBufferImpl *psImpl; |
| +} PVRBuffer; |
| + |
| +extern const __DRIextension *apsScreenExtensions[]; |
| +extern const __DRIextension asScreenExtensionVersionInfo[]; |
| + |
| +/* We need to know the current screen in order to lookup EGL images. */ |
| +static __thread PVRDRIScreen *gpsPVRScreen; |
| + |
| +/*************************************************************************/ /*! |
| + Local functions |
| +*/ /**************************************************************************/ |
| + |
| +static bool PVRLoaderIsSupported(__DRIscreen *psDRIScreen) |
| +{ |
| + if (psDRIScreen->image.loader) |
| + { |
| + if (psDRIScreen->image.loader->base.version < PVR_IMAGE_LOADER_VER_MIN) |
| + { |
| + __driUtilMessage("%s: Image loader extension version %d but need %d", |
| + __func__, |
| + psDRIScreen->image.loader->base.version, |
| + PVR_IMAGE_LOADER_VER_MIN); |
| + return false; |
| + } |
| + else if (!psDRIScreen->image.loader->getBuffers) |
| + { |
| + __driUtilMessage("%s: Image loader extension missing support for getBuffers", |
| + __func__); |
| + return false; |
| + } |
| + } |
| + else if (psDRIScreen->dri2.loader) |
| + { |
| + if (psDRIScreen->dri2.loader->base.version < PVR_DRI2_LOADER_VER_MIN) |
| + { |
| + __driUtilMessage("%s: DRI2 loader extension version %d but need %d", |
| + __func__, |
| + psDRIScreen->dri2.loader->base.version, |
| + PVR_DRI2_LOADER_VER_MIN); |
| + return false; |
| + } |
| + else if (!psDRIScreen->dri2.loader->getBuffersWithFormat) |
| + { |
| + __driUtilMessage("%s: DRI2 loader extension missing support for getBuffersWithFormat", |
| + __func__); |
| + return false; |
| + } |
| + } |
| + else |
| + { |
| + __driUtilMessage("%s: Missing required loader extension (need " |
| + "either the image or DRI2 loader extension)", |
| + __func__); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +static bool PVRMutexInit(pthread_mutex_t *psMutex, int iType) |
| +{ |
| + pthread_mutexattr_t sMutexAttr; |
| + int res; |
| + |
| + res = pthread_mutexattr_init(&sMutexAttr); |
| + if (res != 0) |
| + { |
| + __driUtilMessage("%s: pthread_mutexattr_init failed (%d)", |
| + __func__, |
| + res); |
| + return false; |
| + } |
| + |
| + res = pthread_mutexattr_settype(&sMutexAttr, iType); |
| + if (res != 0) |
| + { |
| + __driUtilMessage("%s: pthread_mutexattr_settype failed (%d)", |
| + __func__, |
| + res); |
| + goto ErrorMutexAttrDestroy; |
| + } |
| + |
| + res = pthread_mutex_init(psMutex, &sMutexAttr); |
| + if (res != 0) |
| + { |
| + __driUtilMessage("%s: pthread_mutex_init failed (%d)", |
| + __func__, |
| + res); |
| + goto ErrorMutexAttrDestroy; |
| + } |
| + |
| + (void) pthread_mutexattr_destroy(&sMutexAttr); |
| + |
| + return true; |
| + |
| +ErrorMutexAttrDestroy: |
| + (void) pthread_mutexattr_destroy(&sMutexAttr); |
| + |
| + return false; |
| +} |
| + |
| +static void PVRMutexDeinit(pthread_mutex_t *psMutex) |
| +{ |
| + int res; |
| + |
| + res = pthread_mutex_destroy(psMutex); |
| + if (res != 0) |
| + { |
| + __driUtilMessage("%s: pthread_mutex_destroy failed (%d)", |
| + __func__, |
| + res); |
| + } |
| +} |
| + |
| +static inline bool |
| +PVRDRIFlushBuffers(PVRDRIContext *psPVRContext, |
| + PVRDRIDrawable *psPVRDrawable, |
| + uint32_t uiFlags) |
| +{ |
| + assert(!(uiFlags & ~(PVRDRI_FLUSH_WAIT_FOR_HW | |
| + PVRDRI_FLUSH_NEW_EXTERNAL_FRAME | |
| + PVRDRI_FLUSH_ALL_SURFACES))); |
| + |
| + return PVRDRIEGLFlushBuffers(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + psPVRDrawable ? psPVRDrawable->psImpl : NULL, |
| + uiFlags & PVRDRI_FLUSH_ALL_SURFACES, |
| + uiFlags & PVRDRI_FLUSH_NEW_EXTERNAL_FRAME, |
| + uiFlags & PVRDRI_FLUSH_WAIT_FOR_HW); |
| +} |
| + |
| +bool |
| +PVRDRIFlushBuffersForSwap(PVRDRIContext *psPVRContext, |
| + PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRDRIContext *psPVRFlushContext; |
| + uint32_t uiFlushFlags; |
| + uint32_t uiFlags = 0; |
| + PVRQElem *psQElem; |
| + |
| + if (psPVRContext) |
| + { |
| + return PVRDRIFlushBuffers(psPVRContext, psPVRDrawable, |
| + PVRDRI_FLUSH_NEW_EXTERNAL_FRAME); |
| + } |
| + |
| + for (psQElem = psPVRDrawable->sPVRContextHead.pvForw; |
| + psQElem != &psPVRDrawable->sPVRContextHead; |
| + psQElem = psPVRFlushContext->sQElem.pvForw) |
| + { |
| + psPVRFlushContext = |
| + PVRQ_CONTAINER_OF(psQElem, PVRDRIContext, sQElem); |
| + uiFlushFlags = uiFlags; |
| + |
| + if (!psPVRContext || psPVRContext == psPVRFlushContext) |
| + { |
| + uiFlushFlags |= PVRDRI_FLUSH_NEW_EXTERNAL_FRAME; |
| + } |
| + |
| + (void) PVRDRIFlushBuffers(psPVRFlushContext, psPVRDrawable, |
| + uiFlushFlags); |
| + } |
| + |
| + return true; |
| +} |
| + |
| +static bool |
| +PVRDRIFlushBuffersGC(PVRDRIContext *psPVRContext) |
| +{ |
| + return PVRDRIFlushBuffers(psPVRContext, NULL, |
| + PVRDRI_FLUSH_WAIT_FOR_HW | |
| + PVRDRI_FLUSH_ALL_SURFACES); |
| +} |
| + |
| +static void PVRDRIDisplayFrontBuffer(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + if (!psPVRDrawable->bDoubleBuffered) |
| + { |
| + PVRDRIScreen *psPVRScreen = psPVRDrawable->psPVRScreen; |
| + __DRIscreen *psDRIScreen = psPVRScreen->psDRIScreen; |
| + |
| + if (psDRIScreen->image.loader && psDRIScreen->image.loader->flushFrontBuffer) |
| + { |
| + psDRIScreen->image.loader->flushFrontBuffer(psPVRDrawable->psDRIDrawable, |
| + psPVRDrawable->psDRIDrawable->loaderPrivate); |
| + } |
| + else if (psDRIScreen->dri2.loader && psDRIScreen->dri2.loader->flushFrontBuffer) |
| + { |
| + psDRIScreen->dri2.loader->flushFrontBuffer(psPVRDrawable->psDRIDrawable, |
| + psPVRDrawable->psDRIDrawable->loaderPrivate); |
| + } |
| + } |
| +} |
| + |
| +static void PVRContextUnbind(PVRDRIContext *psPVRContext, |
| + bool bMakeUnCurrent, |
| + bool bMarkSurfaceInvalid) |
| +{ |
| + if (bMakeUnCurrent || psPVRContext->psPVRDrawable != NULL) |
| + { |
| + (void) PVRDRIFlushBuffersGC(psPVRContext); |
| + } |
| + |
| + if (bMakeUnCurrent) |
| + { |
| + PVRDRIMakeUnCurrentGC(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl); |
| + } |
| + |
| + if (psPVRContext->psPVRDrawable != NULL) |
| + { |
| + if (bMarkSurfaceInvalid) |
| + { |
| + PVRDRIEGLMarkRendersurfaceInvalid(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl); |
| + } |
| + |
| + psPVRContext->psPVRDrawable = NULL; |
| + } |
| + |
| + PVRQDequeue(&psPVRContext->sQElem); |
| +} |
| + |
| +static inline PVRDRIContextImpl * |
| +getSharedContextImpl(void *pvSharedContextPrivate) |
| +{ |
| + if (pvSharedContextPrivate == NULL) |
| + { |
| + return NULL; |
| + } |
| + return ((PVRDRIContext *)pvSharedContextPrivate)->psImpl; |
| +} |
| + |
| + |
| +static inline void PVRDRIConfigFromMesa(PVRDRIConfigInfo *psConfigInfo, |
| + const struct gl_config *psGLMode) |
| +{ |
| + memset(psConfigInfo, 0, sizeof(*psConfigInfo)); |
| + |
| + if (psGLMode) |
| + { |
| + psConfigInfo->samples = psGLMode->samples; |
| + psConfigInfo->redBits = psGLMode->redBits; |
| + psConfigInfo->greenBits = psGLMode->greenBits; |
| + psConfigInfo->blueBits = psGLMode->blueBits; |
| + psConfigInfo->alphaBits = psGLMode->alphaBits; |
| + psConfigInfo->rgbBits = psGLMode->rgbBits; |
| + psConfigInfo->depthBits = psGLMode->depthBits; |
| + psConfigInfo->stencilBits = psGLMode->stencilBits; |
| + psConfigInfo->doubleBufferMode = psGLMode->doubleBufferMode; |
| + |
| + psConfigInfo->sampleBuffers = psGLMode->sampleBuffers; |
| + psConfigInfo->bindToTextureRgb = psGLMode->bindToTextureRgb; |
| + psConfigInfo->bindToTextureRgba = psGLMode->bindToTextureRgba; |
| + } |
| +} |
| + |
| +static void PVRDRIScreenAddReference(PVRDRIScreen *psPVRScreen) |
| +{ |
| + int iRefCount = __sync_fetch_and_add(&psPVRScreen->iRefCount, 1); |
| + (void)iRefCount; |
| + assert(iRefCount > 0); |
| +} |
| + |
| +static void PVRDRIScreenRemoveReference(PVRDRIScreen *psPVRScreen) |
| +{ |
| + int iRefCount = __sync_sub_and_fetch(&psPVRScreen->iRefCount, 1); |
| + |
| + assert(iRefCount >= 0); |
| + |
| + if (iRefCount) |
| + { |
| + return; |
| + } |
| + |
| + pvrdri_free_dispatch_tables(psPVRScreen); |
| + |
| + (void)PVRDRIEGLFreeResources(psPVRScreen->psImpl); |
| + |
| + PVRDRIDestroyFencesImpl(psPVRScreen->psImpl); |
| + |
| + PVRDRIDestroyScreenImpl(psPVRScreen->psImpl); |
| + PVRMutexDeinit(&psPVRScreen->sMutex); |
| + |
| + free(psPVRScreen); |
| +} |
| + |
| +static inline void PVRDrawableUnbindContexts(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRQElem *psQElem = psPVRDrawable->sPVRContextHead.pvForw; |
| + |
| + while (psQElem != &psPVRDrawable->sPVRContextHead) |
| + { |
| + PVRDRIContext *psPVRContext = PVRQ_CONTAINER_OF(psQElem, |
| + PVRDRIContext, |
| + sQElem); |
| + |
| + /* Get the next element in the list now, as the list will be modified */ |
| + psQElem = psPVRContext->sQElem.pvForw; |
| + |
| + /* Draw surface? */ |
| + if (psPVRContext->psPVRDrawable == psPVRDrawable) |
| + { |
| + PVRContextUnbind(psPVRContext, false, true); |
| + } |
| + /* Pixmap? */ |
| + else |
| + { |
| + (void) PVRDRIFlushBuffersGC(psPVRContext); |
| + PVRQDequeue(&psPVRContext->sQElem); |
| + } |
| + } |
| +} |
| + |
| +static void PVRScreenPrintExtensions(__DRIscreen *psDRIScreen) |
| +{ |
| + /* Don't attempt to print anything if LIBGL_DEBUG isn't in the environment */ |
| + if (getenv("LIBGL_DEBUG") == NULL) |
| + { |
| + return; |
| + } |
| + |
| + if (psDRIScreen->extensions) |
| + { |
| + int i; |
| + int j; |
| + |
| + __driUtilMessage("Supported screen extensions:"); |
| + |
| + for (i = 0; psDRIScreen->extensions[i]; i++) |
| + { |
| + for (j = 0; asScreenExtensionVersionInfo[j].name; j++) |
| + { |
| + if (strcmp(psDRIScreen->extensions[i]->name, |
| + asScreenExtensionVersionInfo[j].name) == 0) |
| + { |
| + __driUtilMessage("\t%s (supported version: %u - max version: %u)", |
| + psDRIScreen->extensions[i]->name, |
| + psDRIScreen->extensions[i]->version, |
| + asScreenExtensionVersionInfo[j].version); |
| + break; |
| + } |
| + } |
| + |
| + if (asScreenExtensionVersionInfo[j].name == NULL) |
| + { |
| + __driUtilMessage("\t%s (supported version: %u - max version: unknown)", |
| + psDRIScreen->extensions[i]->name, |
| + psDRIScreen->extensions[i]->version); |
| + } |
| + } |
| + } |
| + else |
| + { |
| + __driUtilMessage("No screen extensions found"); |
| + } |
| +} |
| + |
| + |
| +/*************************************************************************/ /*! |
| + Mesa driver API functions |
| +*/ /**************************************************************************/ |
| +static const __DRIconfig **PVRDRIInitScreen(__DRIscreen *psDRIScreen) |
| +{ |
| + PVRDRIScreen *psPVRScreen; |
| + const __DRIconfig **configs; |
| + PVRDRICallbacks sDRICallbacks = { |
| + .DrawableRecreate = PVRDRIDrawableRecreate, |
| + .DrawableGetParameters = PVRDRIDrawableGetParameters, |
| + .ImageGetSharedType = PVRDRIImageGetSharedType, |
| + .ImageGetSharedBuffer = PVRDRIImageGetSharedBuffer, |
| + .ImageGetSharedEGLImage = PVRDRIImageGetSharedEGLImage, |
| + .ImageGetEGLImage = PVRDRIImageGetEGLImage, |
| + .ScreenGetDRIImage = PVRDRIScreenGetDRIImage, |
| + .RefImage = PVRDRIRefImage, |
| + .UnrefImage = PVRDRIUnrefImage, |
| + }; |
| + |
| + if (!PVRLoaderIsSupported(psDRIScreen)) |
| + { |
| + return NULL; |
| + } |
| + |
| + PVRDRIRegisterCallbacks(&sDRICallbacks); |
| + |
| + psPVRScreen = calloc(1, sizeof(*psPVRScreen)); |
| + if (psPVRScreen == NULL) |
| + { |
| + __driUtilMessage("%s: Couldn't allocate PVRDRIScreen", |
| + __func__); |
| + return NULL; |
| + } |
| + |
| + DRIScreenPrivate(psDRIScreen) = psPVRScreen; |
| + psPVRScreen->psDRIScreen = psDRIScreen; |
| + |
| + /* |
| + * KEGLGetDrawableParameters could be called with the mutex either |
| + * locked or unlocked, hence the use of a recursive mutex. |
| + */ |
| + if (!PVRMutexInit(&psPVRScreen->sMutex, PTHREAD_MUTEX_RECURSIVE)) |
| + { |
| + __driUtilMessage("%s: Screen mutex initialisation failed", |
| + __func__); |
| + goto ErrorScreenFree; |
| + } |
| + |
| + psPVRScreen->iRefCount = 1; |
| + psPVRScreen->bUseInvalidate = (psDRIScreen->dri2.useInvalidate != NULL); |
| + |
| + psDRIScreen->extensions = apsScreenExtensions; |
| + |
| + psPVRScreen->psImpl = PVRDRICreateScreenImpl(psDRIScreen->fd); |
| + if (psPVRScreen->psImpl == NULL) |
| + { |
| + goto ErrorScreenMutexDeinit; |
| + } |
| + |
| + /* |
| + * OpenGL doesn't support concurrent EGL displays so only advertise |
| + * OpenGL support for the first display. |
| + */ |
| + if (PVRDRIIsFirstScreen(psPVRScreen->psImpl)) |
| + { |
| + psDRIScreen->max_gl_compat_version = |
| + PVRDRIAPIVersion(PVRDRI_API_GL, |
| + PVRDRI_API_SUB_GL_COMPAT, |
| + psPVRScreen->psImpl); |
| + psDRIScreen->max_gl_core_version = |
| + PVRDRIAPIVersion(PVRDRI_API_GL, |
| + PVRDRI_API_SUB_GL_CORE, |
| + psPVRScreen->psImpl); |
| + } |
| + |
| + psDRIScreen->max_gl_es1_version = |
| + PVRDRIAPIVersion(PVRDRI_API_GLES1, |
| + PVRDRI_API_SUB_NONE, |
| + psPVRScreen->psImpl); |
| + |
| + psDRIScreen->max_gl_es2_version = |
| + PVRDRIAPIVersion(PVRDRI_API_GLES2, |
| + PVRDRI_API_SUB_NONE, |
| + psPVRScreen->psImpl); |
| + |
| + configs = PVRDRICreateConfigs(); |
| + if (configs == NULL) |
| + { |
| + __driUtilMessage("%s: No framebuffer configs", __func__); |
| + goto ErrorScreenImplDeinit; |
| + } |
| + |
| + PVRScreenPrintExtensions(psDRIScreen); |
| + |
| + return configs; |
| + |
| +ErrorScreenImplDeinit: |
| + PVRDRIDestroyScreenImpl(psPVRScreen->psImpl); |
| + |
| +ErrorScreenMutexDeinit: |
| + PVRMutexDeinit(&psPVRScreen->sMutex); |
| + |
| +ErrorScreenFree: |
| + free(psPVRScreen); |
| + |
| + return NULL; |
| +} |
| + |
| +static void PVRDRIDestroyScreen(__DRIscreen *psDRIScreen) |
| +{ |
| + PVRDRIScreenRemoveReference(DRIScreenPrivate(psDRIScreen)); |
| +} |
| + |
| +static EGLint PVRDRIScreenSupportedAPIs(PVRDRIScreen *psPVRScreen) |
| +{ |
| + unsigned api_mask = psPVRScreen->psDRIScreen->api_mask; |
| + EGLint supported = 0; |
| + |
| + if ((api_mask & (1 << __DRI_API_OPENGL)) != 0) |
| + { |
| + supported |= PVRDRI_API_BIT_GL; |
| + } |
| + |
| + if ((api_mask & (1 << __DRI_API_GLES)) != 0) |
| + { |
| + supported |= PVRDRI_API_BIT_GLES; |
| + } |
| + |
| + if ((api_mask & (1 << __DRI_API_GLES2)) != 0) |
| + { |
| + supported |= PVRDRI_API_BIT_GLES2; |
| + } |
| + |
| + if ((api_mask & (1 << __DRI_API_OPENGL_CORE)) != 0) |
| + { |
| + supported |= PVRDRI_API_BIT_GL; |
| + } |
| + |
| + if ((api_mask & (1 << __DRI_API_GLES3)) != 0) |
| + { |
| + supported |= PVRDRI_API_BIT_GLES3; |
| + } |
| + |
| + return supported; |
| +} |
| + |
| +static GLboolean PVRDRICreateContext(gl_api eMesaAPI, |
| + const struct gl_config *psGLMode, |
| + __DRIcontext *psDRIContext, |
| + unsigned uMajorVersion, |
| + unsigned uMinorVersion, |
| + uint32_t uFlags, |
| + bool notify_reset, |
| + unsigned *puError, |
| + void *pvSharedContextPrivate) |
| +{ |
| + __DRIscreen *psDRIScreen = psDRIContext->driScreenPriv; |
| + PVRDRIScreen *psPVRScreen = (PVRDRIScreen *)DRIScreenPrivate(psDRIScreen); |
| + PVRDRIContext *psPVRContext; |
| + unsigned uPriority; |
| + PVRDRIAPISubType eAPISub = PVRDRI_API_SUB_NONE; |
| + PVRDRIConfigInfo sConfigInfo; |
| + bool bResult; |
| + |
| + psPVRContext = calloc(1, sizeof(*psPVRContext)); |
| + if (psPVRContext == NULL) |
| + { |
| + __driUtilMessage("%s: Couldn't allocate PVRDRIContext", |
| + __func__); |
| + *puError = __DRI_CTX_ERROR_NO_MEMORY; |
| + return GL_FALSE; |
| + } |
| + |
| + psPVRContext->psDRIContext = psDRIContext; |
| + psPVRContext->psPVRScreen = psPVRScreen; |
| + |
| +#if defined(__DRI_PRIORITY) |
| + uPriority = psDRIContext->priority; |
| +#else |
| + uPriority = PVRDRI_CONTEXT_PRIORITY_MEDIUM; |
| +#endif |
| + |
| + switch (eMesaAPI) |
| + { |
| + case API_OPENGL_COMPAT: |
| + psPVRContext->eAPI = PVRDRI_API_GL; |
| + eAPISub = PVRDRI_API_SUB_GL_COMPAT; |
| + break; |
| + case API_OPENGL_CORE: |
| + psPVRContext->eAPI = PVRDRI_API_GL; |
| + eAPISub = PVRDRI_API_SUB_GL_CORE; |
| + break; |
| + case API_OPENGLES: |
| + psPVRContext->eAPI = PVRDRI_API_GLES1; |
| + break; |
| + case API_OPENGLES2: |
| + psPVRContext->eAPI = PVRDRI_API_GLES2; |
| + break; |
| + default: |
| + __driUtilMessage("%s: Unsupported API: %d", |
| + __func__, |
| + (int)eMesaAPI); |
| + goto ErrorContextFree; |
| + } |
| + |
| + PVRDRIConfigFromMesa(&sConfigInfo, psGLMode); |
| + |
| + *puError = PVRDRICreateContextImpl(&psPVRContext->psImpl, |
| + psPVRContext->eAPI, |
| + eAPISub, |
| + psPVRScreen->psImpl, |
| + &sConfigInfo, |
| + uMajorVersion, |
| + uMinorVersion, |
| + uFlags, |
| + notify_reset, |
| + uPriority, |
| + getSharedContextImpl(pvSharedContextPrivate)); |
| + if (*puError != __DRI_CTX_ERROR_SUCCESS) |
| + { |
| + goto ErrorContextFree; |
| + } |
| + |
| + /* |
| + * The dispatch table must be created after the context, because |
| + * PVRDRIContextCreate loads the API library, and we need the |
| + * library handle to populate the dispatch table. |
| + */ |
| + PVRDRIScreenLock(psPVRScreen); |
| + bResult = pvrdri_create_dispatch_table(psPVRScreen, psPVRContext->eAPI); |
| + PVRDRIScreenUnlock(psPVRScreen); |
| + |
| + if (!bResult) |
| + { |
| + __driUtilMessage("%s: Couldn't create dispatch table", |
| + __func__); |
| + *puError = __DRI_CTX_ERROR_BAD_API; |
| + goto ErrorContextDestroy; |
| + } |
| + |
| + psDRIContext->driverPrivate = (void *)psPVRContext; |
| + PVRDRIScreenAddReference(psPVRScreen); |
| + |
| + *puError = __DRI_CTX_ERROR_SUCCESS; |
| + |
| + return GL_TRUE; |
| + |
| +ErrorContextDestroy: |
| + PVRDRIDestroyContextImpl(psPVRContext->psImpl, |
| + psPVRContext->eAPI, |
| + psPVRScreen->psImpl); |
| +ErrorContextFree: |
| + free(psPVRContext); |
| + |
| + return GL_FALSE; |
| +} |
| + |
| +static void PVRDRIDestroyContext(__DRIcontext *psDRIContext) |
| +{ |
| + PVRDRIContext *psPVRContext = (PVRDRIContext *)psDRIContext->driverPrivate; |
| + PVRDRIScreen *psPVRScreen = psPVRContext->psPVRScreen; |
| + |
| + PVRDRIScreenLock(psPVRScreen); |
| + |
| + PVRContextUnbind(psPVRContext, false, false); |
| + |
| + PVRDRIDestroyContextImpl(psPVRContext->psImpl, |
| + psPVRContext->eAPI, |
| + psPVRScreen->psImpl); |
| + |
| + free(psPVRContext); |
| + |
| + PVRDRIScreenUnlock(psPVRScreen); |
| + |
| + PVRDRIScreenRemoveReference(psPVRScreen); |
| +} |
| + |
| +static IMG_PIXFMT PVRDRIGetPixelFormat(const struct gl_config *psGLMode) |
| +{ |
| + switch (psGLMode->rgbBits) |
| + { |
| + case 32: |
| + case 24: |
| + if (psGLMode->redMask == 0x00FF0000 && |
| + psGLMode->greenMask == 0x0000FF00 && |
| + psGLMode->blueMask == 0x000000FF) |
| + { |
| + if (psGLMode->alphaMask == 0xFF000000) |
| + { |
| + return IMG_PIXFMT_B8G8R8A8_UNORM; |
| + } |
| + else if (psGLMode->alphaMask == 0) |
| + { |
| + return IMG_PIXFMT_B8G8R8X8_UNORM; |
| + } |
| + } |
| + |
| + if (psGLMode->redMask == 0x000000FF && |
| + psGLMode->greenMask == 0x0000FF00 && |
| + psGLMode->blueMask == 0x00FF0000) |
| + { |
| + if (psGLMode->alphaMask == 0xFF000000) |
| + { |
| + return IMG_PIXFMT_R8G8B8A8_UNORM; |
| + } |
| + else if (psGLMode->alphaMask == 0) |
| + { |
| + return IMG_PIXFMT_R8G8B8X8_UNORM; |
| + } |
| + } |
| + |
| + __driUtilMessage("%s: Unsupported buffer format", __func__); |
| + return IMG_PIXFMT_UNKNOWN; |
| + |
| + case 16: |
| + if (psGLMode->redMask == 0xF800 && |
| + psGLMode->greenMask == 0x07E0 && |
| + psGLMode->blueMask == 0x001F) |
| + { |
| + return IMG_PIXFMT_B5G6R5_UNORM; |
| + } |
| + |
| + default: |
| + errorMessage("%s: Unsupported screen format\n", __func__); |
| + return IMG_PIXFMT_UNKNOWN; |
| + } |
| +} |
| + |
| +static GLboolean PVRDRICreateBuffer(__DRIscreen *psDRIScreen, |
| + __DRIdrawable *psDRIDrawable, |
| + const struct gl_config *psGLMode, |
| + GLboolean bIsPixmap) |
| +{ |
| + PVRDRIScreen *psPVRScreen = DRIScreenPrivate(psDRIScreen); |
| + PVRDRIDrawable *psPVRDrawable = NULL; |
| + PVRDRIDrawableImpl *psDrawableImpl = NULL; |
| + EGLint supportedAPIs = PVRDRIScreenSupportedAPIs(psPVRScreen); |
| + PVRDRIConfigInfo sConfigInfo; |
| + |
| + /* No known callers ever set this to true */ |
| + if (bIsPixmap) |
| + { |
| + return GL_FALSE; |
| + } |
| + |
| + if (!psGLMode) |
| + { |
| + __driUtilMessage("%s: Invalid GL config", __func__); |
| + return GL_FALSE; |
| + } |
| + |
| + psPVRDrawable = calloc(1, sizeof(*psPVRDrawable)); |
| + if (!psPVRDrawable) |
| + { |
| + __driUtilMessage("%s: Couldn't allocate PVR drawable", __func__); |
| + goto ErrorDrawableFree; |
| + } |
| + |
| + psDrawableImpl = PVRDRICreateDrawableImpl(psPVRDrawable); |
| + if (!psDrawableImpl) |
| + { |
| + __driUtilMessage("%s: Couldn't allocate PVR drawable", __func__); |
| + goto ErrorDrawableFree; |
| + } |
| + |
| + psPVRDrawable->psImpl = psDrawableImpl; |
| + |
| + psDRIDrawable->driverPrivate = (void *)psPVRDrawable; |
| + |
| + INITIALISE_PVRQ_HEAD(&psPVRDrawable->sPVRContextHead); |
| + |
| + psPVRDrawable->psDRIDrawable = psDRIDrawable; |
| + psPVRDrawable->psPVRScreen = psPVRScreen; |
| + psPVRDrawable->bDoubleBuffered = psGLMode->doubleBufferMode; |
| + |
| + psPVRDrawable->ePixelFormat = PVRDRIGetPixelFormat(psGLMode); |
| + if (psPVRDrawable->ePixelFormat == IMG_PIXFMT_UNKNOWN) |
| + { |
| + __driUtilMessage("%s: Couldn't work out pixel format", __func__); |
| + goto ErrorDrawableFree; |
| + } |
| + |
| + if (!PVRMutexInit(&psPVRDrawable->sMutex, PTHREAD_MUTEX_RECURSIVE)) |
| + { |
| + __driUtilMessage("%s: Couldn't initialise drawable mutex", __func__); |
| + goto ErrorDrawableFree; |
| + } |
| + |
| + PVRDRIConfigFromMesa(&sConfigInfo, psGLMode); |
| + if (!PVRDRIEGLDrawableConfigFromGLMode(psDrawableImpl, |
| + &sConfigInfo, |
| + supportedAPIs, |
| + psPVRDrawable->ePixelFormat)) |
| + { |
| + __driUtilMessage("%s: Couldn't derive EGL config", __func__); |
| + goto ErrorDrawableMutexDeinit; |
| + } |
| + |
| + /* Initialisation is completed in MakeCurrent */ |
| + PVRDRIScreenAddReference(psPVRScreen); |
| + return GL_TRUE; |
| + |
| +ErrorDrawableMutexDeinit: |
| + PVRMutexDeinit(&psPVRDrawable->sMutex); |
| + |
| +ErrorDrawableFree: |
| + PVRDRIDestroyDrawableImpl(psDrawableImpl); |
| + free(psPVRDrawable); |
| + psDRIDrawable->driverPrivate = NULL; |
| + |
| + return GL_FALSE; |
| +} |
| + |
| +static void PVRDRIDestroyBuffer(__DRIdrawable *psDRIDrawable) |
| +{ |
| + PVRDRIDrawable *psPVRDrawable = (PVRDRIDrawable *)psDRIDrawable->driverPrivate; |
| + PVRDRIScreen *psPVRScreen = psPVRDrawable->psPVRScreen; |
| + |
| + PVRDRIScreenLock(psPVRScreen); |
| + |
| + PVRDrawableUnbindContexts(psPVRDrawable); |
| + |
| + PVRDRIDrawableDeinit(psPVRDrawable); |
| + |
| + PVREGLDrawableDestroyConfig(psPVRDrawable->psImpl); |
| + |
| + PVRMutexDeinit(&psPVRDrawable->sMutex); |
| + |
| + PVRDRIDestroyDrawableImpl(psPVRDrawable->psImpl); |
| + |
| + free(psPVRDrawable); |
| + |
| + PVRDRIScreenUnlock(psPVRScreen); |
| + |
| + PVRDRIScreenRemoveReference(psPVRScreen); |
| +} |
| + |
| +static GLboolean PVRDRIMakeCurrent(__DRIcontext *psDRIContext, |
| + __DRIdrawable *psDRIWrite, |
| + __DRIdrawable *psDRIRead) |
| +{ |
| + PVRDRIContext *psPVRContext = (PVRDRIContext *)psDRIContext->driverPrivate; |
| + PVRDRIDrawable *psPVRWrite = (psDRIWrite) ? (PVRDRIDrawable *)psDRIWrite->driverPrivate : NULL; |
| + PVRDRIDrawable *psPVRRead = (psDRIRead) ? (PVRDRIDrawable *)psDRIRead->driverPrivate : NULL; |
| + |
| + PVRDRIScreenLock(psPVRContext->psPVRScreen); |
| + |
| + if (psPVRWrite != NULL) |
| + { |
| + if (!PVRDRIDrawableInit(psPVRWrite)) |
| + { |
| + __driUtilMessage("%s: Couldn't initialise write drawable", |
| + __func__); |
| + goto ErrorUnlock; |
| + } |
| + } |
| + |
| + if (psPVRRead != NULL) |
| + { |
| + if (!PVRDRIDrawableInit(psPVRRead)) |
| + { |
| + __driUtilMessage("%s: Couldn't initialise read drawable", |
| + __func__); |
| + goto ErrorUnlock; |
| + } |
| + } |
| + |
| + if (!PVRDRIMakeCurrentGC(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + psPVRWrite == NULL ? NULL : psPVRWrite->psImpl, |
| + psPVRRead == NULL ? NULL : psPVRRead->psImpl)) |
| + { |
| + goto ErrorUnlock; |
| + } |
| + |
| + PVRQDequeue(&psPVRContext->sQElem); |
| + |
| + if (psPVRWrite != NULL) |
| + { |
| + PVRQQueue(&psPVRWrite->sPVRContextHead, &psPVRContext->sQElem); |
| + } |
| + |
| + psPVRContext->psPVRDrawable = psPVRWrite; |
| + |
| + if (psPVRWrite != NULL && psPVRContext->eAPI == PVRDRI_API_GL) |
| + { |
| + PVRDRIEGLSetFrontBufferCallback(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRWrite->psImpl, |
| + PVRDRIDisplayFrontBuffer); |
| + } |
| + |
| + pvrdri_set_dispatch_table(psPVRContext); |
| + |
| + PVRDRIThreadSetCurrentScreen(psPVRContext->psPVRScreen); |
| + |
| + PVRDRIScreenUnlock(psPVRContext->psPVRScreen); |
| + |
| + return GL_TRUE; |
| + |
| +ErrorUnlock: |
| + PVRDRIScreenUnlock(psPVRContext->psPVRScreen); |
| + |
| + return GL_FALSE; |
| +} |
| + |
| +static GLboolean PVRDRIUnbindContext(__DRIcontext *psDRIContext) |
| +{ |
| + PVRDRIContext *psPVRContext = (PVRDRIContext *)psDRIContext->driverPrivate; |
| + PVRDRIScreen *psPVRScreen = psPVRContext->psPVRScreen; |
| + |
| + pvrdri_set_null_dispatch_table(); |
| + |
| + PVRDRIScreenLock(psPVRScreen); |
| + PVRContextUnbind(psPVRContext, true, false); |
| + PVRDRIThreadSetCurrentScreen(NULL); |
| + PVRDRIScreenUnlock(psPVRScreen); |
| + |
| + return GL_TRUE; |
| +} |
| + |
| +static __DRIbuffer *PVRDRIAllocateBuffer(__DRIscreen *psDRIScreen, |
| + unsigned int uAttachment, |
| + unsigned int uFormat, |
| + int iWidth, |
| + int iHeight) |
| +{ |
| + PVRDRIScreen *psPVRScreen = DRIScreenPrivate(psDRIScreen); |
| + PVRBuffer *psBuffer; |
| + unsigned int uiBpp; |
| + |
| + /* GEM names are only supported on primary nodes */ |
| + if (drmGetNodeTypeFromFd(psDRIScreen->fd) != DRM_NODE_PRIMARY) |
| + { |
| + __driUtilMessage("%s: Cannot allocate buffer", __func__); |
| + return NULL; |
| + } |
| + |
| + /* This is based upon PVRDRIGetPixelFormat */ |
| + switch (uFormat) |
| + { |
| + case 32: |
| + case 16: |
| + /* Format (depth) and bpp match */ |
| + uiBpp = uFormat; |
| + break; |
| + case 24: |
| + uiBpp = 32; |
| + break; |
| + default: |
| + __driUtilMessage("%s: Unsupported format '%u'", |
| + __func__, uFormat); |
| + return NULL; |
| + } |
| + |
| + psBuffer = calloc(1, sizeof(*psBuffer)); |
| + if (psBuffer == NULL) |
| + { |
| + __driUtilMessage("%s: Failed to allocate buffer", __func__); |
| + return NULL; |
| + } |
| + |
| + psBuffer->psImpl = PVRDRIBufferCreate(psPVRScreen->psImpl, |
| + iWidth, |
| + iHeight, |
| + uiBpp, |
| + PVDRI_BUFFER_USE_SHARE, |
| + &psBuffer->sDRIBuffer.pitch); |
| + if (!psBuffer->psImpl) |
| + { |
| + __driUtilMessage("%s: Failed to create backing buffer", |
| + __func__); |
| + goto ErrorFreeDRIBuffer; |
| + } |
| + |
| + psBuffer->sDRIBuffer.attachment = uAttachment; |
| + psBuffer->sDRIBuffer.name = PVRDRIBufferGetName(psBuffer->psImpl); |
| + psBuffer->sDRIBuffer.cpp = uiBpp / 8; |
| + |
| + return &psBuffer->sDRIBuffer; |
| + |
| +ErrorFreeDRIBuffer: |
| + free(psBuffer); |
| + |
| + return NULL; |
| +} |
| + |
| +static void PVRDRIReleaseBuffer(__DRIscreen *psDRIScreen, |
| + __DRIbuffer *psDRIBuffer) |
| +{ |
| + PVRBuffer *psBuffer = (PVRBuffer *)psDRIBuffer; |
| + |
| + (void)psDRIScreen; |
| + |
| + PVRDRIBufferDestroy(psBuffer->psImpl); |
| + free(psBuffer); |
| +} |
| + |
| +/* Publish our driver implementation to the world. */ |
| +static const struct __DriverAPIRec pvr_driver_api = |
| +{ |
| + .InitScreen = PVRDRIInitScreen, |
| + .DestroyScreen = PVRDRIDestroyScreen, |
| + .CreateContext = PVRDRICreateContext, |
| + .DestroyContext = PVRDRIDestroyContext, |
| + .CreateBuffer = PVRDRICreateBuffer, |
| + .DestroyBuffer = PVRDRIDestroyBuffer, |
| + .SwapBuffers = NULL, |
| + .MakeCurrent = PVRDRIMakeCurrent, |
| + .UnbindContext = PVRDRIUnbindContext, |
| + .AllocateBuffer = PVRDRIAllocateBuffer, |
| + .ReleaseBuffer = PVRDRIReleaseBuffer, |
| +}; |
| + |
| +static const struct __DRIDriverVtableExtensionRec pvr_vtable = { |
| + .base = { __DRI_DRIVER_VTABLE, 1 }, |
| + .vtable = &pvr_driver_api, |
| +}; |
| + |
| +static const __DRIextension *pvr_driver_extensions[] = { |
| + &driCoreExtension.base, |
| + &driImageDriverExtension.base, |
| + &driDRI2Extension.base, |
| + &pvr_vtable.base, |
| + NULL |
| +}; |
| + |
| +const __DRIextension **__driDriverGetExtensions_pvr(void); |
| +PUBLIC const __DRIextension **__driDriverGetExtensions_pvr(void) |
| +{ |
| + globalDriverAPI = &pvr_driver_api; |
| + |
| + return pvr_driver_extensions; |
| +} |
| + |
| +/*************************************************************************/ /*! |
| + Global functions |
| +*/ /**************************************************************************/ |
| + |
| +/*********************************************************************************** |
| + Function Name : PVRDRIDrawableLock |
| + Inputs : psPVRDrawable - PVRDRI drawable structure |
| + Returns : Boolean |
| + Description : Lock drawable mutex (can be called recursively) |
| +************************************************************************************/ |
| +void PVRDRIDrawableLock(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + int res; |
| + |
| + res = pthread_mutex_lock(&psPVRDrawable->sMutex); |
| + if (res != 0) |
| + { |
| + errorMessage("%s: Failed to lock drawable (%d)\n", __func__, res); |
| + abort(); |
| + } |
| +} |
| + |
| +/*********************************************************************************** |
| + Function Name : PVRDRIDrawableUnlock |
| + Inputs : psPVRDrawable - PVRDRI drawable structure |
| + Returns : Boolean |
| + Description : Unlock drawable mutex (can be called recursively) |
| +************************************************************************************/ |
| +void PVRDRIDrawableUnlock(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + int res; |
| + |
| + res = pthread_mutex_unlock(&psPVRDrawable->sMutex); |
| + if (res != 0) |
| + { |
| + errorMessage("%s: Failed to unlock drawable (%d)\n", __func__, res); |
| + abort(); |
| + } |
| +} |
| + |
| +/*********************************************************************************** |
| + Function Name : PVRDRIScreenLock |
| + Inputs : psPVRScreen - PVRDRI screen structure |
| + Returns : Boolean |
| + Description : Lock screen mutex (can be called recursively) |
| +************************************************************************************/ |
| +void PVRDRIScreenLock(PVRDRIScreen *psPVRScreen) |
| +{ |
| + int res; |
| + |
| + res = pthread_mutex_lock(&psPVRScreen->sMutex); |
| + if (res != 0) |
| + { |
| + errorMessage("%s: Failed to lock screen (%d)\n", __func__, res); |
| + abort(); |
| + } |
| +} |
| + |
| +/*********************************************************************************** |
| + Function Name : PVRDRIScreenUnlock |
| + Inputs : psPVRScreen - PVRDRI screen structure |
| + Returns : Boolean |
| + Description : Unlock screen mutex (can be called recursively) |
| +************************************************************************************/ |
| +void PVRDRIScreenUnlock(PVRDRIScreen *psPVRScreen) |
| +{ |
| + int res; |
| + |
| + res = pthread_mutex_unlock(&psPVRScreen->sMutex); |
| + if (res != 0) |
| + { |
| + errorMessage("%s: Failed to unlock screen (%d)\n", __func__, res); |
| + abort(); |
| + } |
| +} |
| + |
| +void PVRDRIThreadSetCurrentScreen(PVRDRIScreen *psPVRScreen) |
| +{ |
| + gpsPVRScreen = psPVRScreen; |
| +} |
| + |
| +PVRDRIScreen *PVRDRIThreadGetCurrentScreen(void) |
| +{ |
| + return gpsPVRScreen; |
| +} |
| diff --git a/src/mesa/drivers/dri/pvr/pvrdri.h b/src/mesa/drivers/dri/pvr/pvrdri.h |
| new file mode 100644 |
| index 0000000..ea02291 |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrdri.h |
| @@ -0,0 +1,293 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/* |
| + * Copyright (c) Imagination Technologies Ltd. |
| + * |
| + * The contents of this file are subject to the MIT license as set out below. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#if !defined(__PVRDRI2_H__) |
| +#define __PVRDRI2_H__ |
| +#include <stdbool.h> |
| + |
| +#include <glapi/glapi.h> |
| + |
| +#include "main/mtypes.h" |
| +#include "GL/internal/dri_interface.h" |
| + |
| +#include "powervr/dri_support.h" |
| +#include "pvrqueue.h" |
| + |
| +/* This should match EGL_MAX_PLANES */ |
| +#define DRI_PLANES_MAX 3 |
| + |
| +#define DRI2_BUFFERS_MAX (3) |
| + |
| +#define DRIScreenPrivate(pScreen) ((pScreen)->driverPrivate) |
| + |
| +/** Our PVR related screen data */ |
| +typedef struct PVRDRIScreen_TAG |
| +{ |
| + /* DRI screen structure pointer */ |
| + __DRIscreen *psDRIScreen; |
| + /* Mutex for this screen */ |
| + pthread_mutex_t sMutex; |
| + /* X Server sends invalidate events */ |
| + bool bUseInvalidate; |
| + /* Reference count */ |
| + int iRefCount; |
| + |
| + /* PVR OGL dispatch table */ |
| + struct _glapi_table *psPVROGLDispatch; |
| + /* PVR OGLES 1 dispatch table */ |
| + struct _glapi_table *psOGLES1Dispatch; |
| + /* PVR OGLES 2/3 dispatch table */ |
| + struct _glapi_table *psOGLES2Dispatch; |
| + |
| + PVRDRIScreenImpl *psImpl; |
| +} PVRDRIScreen; |
| + |
| +/** Our PVR related context data */ |
| +typedef struct PVRDRIContext_TAG |
| +{ |
| + PVRQElem sQElem; |
| + |
| + /* Pointer to DRI context */ |
| + __DRIcontext *psDRIContext; |
| + /* Pointer to PVRDRIScreen structure */ |
| + PVRDRIScreen *psPVRScreen; |
| + /* Pointer to currently bound drawable */ |
| + struct PVRDRIDrawable_TAG *psPVRDrawable; |
| + |
| + /* API */ |
| + PVRDRIAPIType eAPI; |
| + |
| + PVRDRIContextImpl *psImpl; |
| +} PVRDRIContext; |
| + |
| +typedef struct PVRDRIBuffer_TAG |
| +{ |
| + union |
| + { |
| + struct |
| + { |
| + uint32_t uiName; |
| + PVRDRIBufferImpl *psBuffer; |
| + |
| + } sDRI2; |
| + |
| + struct |
| + { |
| + __DRIimage *psImage; |
| + } sImage; |
| + } uBacking; |
| +} PVRDRIBuffer; |
| + |
| +/** Our PVR related drawable data */ |
| +typedef struct PVRDRIDrawable_TAG |
| +{ |
| + /** Ptr to PVR screen, that spawned this drawable */ |
| + PVRDRIScreen *psPVRScreen; |
| + |
| + /** DRI drawable data */ |
| + __DRIdrawable *psDRIDrawable; |
| + |
| + /** Are surface/buffers created? */ |
| + bool bInitialised; |
| + |
| + /** Are we using double buffering? */ |
| + bool bDoubleBuffered; |
| + |
| + /** Buffer stride */ |
| + unsigned uStride; |
| + |
| + /* Number of bytes per pixel */ |
| + unsigned int uBytesPerPixel; |
| + |
| + /* List of contexts bound to this drawable */ |
| + PVRQHead sPVRContextHead; |
| + |
| + /* Mutex for this drawable */ |
| + pthread_mutex_t sMutex; |
| + |
| + /* IMG Pixel format for this drawable */ |
| + IMG_PIXFMT ePixelFormat; |
| + |
| + /* Indicates the drawable info is invalid */ |
| + bool bDrawableInfoInvalid; |
| + |
| + /* Indicates updated drawable info is available */ |
| + bool bDrawableInfoUpdated; |
| + |
| + /* Indicates the drawable is currently being updated */ |
| + bool bDrawableUpdating; |
| + |
| + /* Indicates a flush is in progress */ |
| + bool bFlushInProgress; |
| + |
| + union { |
| + struct { |
| + __DRIbuffer sDRI; |
| + int w; |
| + int h; |
| + } sBuffer; |
| + struct { |
| + __DRIimage *psDRI; |
| + } sImage; |
| + } uDRI; |
| + PVRDRIBuffer sPVRBuffer; |
| + |
| + PVRDRIDrawableImpl *psImpl; |
| +} PVRDRIDrawable; |
| + |
| +typedef struct PVRDRIImageFormat_TAG |
| +{ |
| + /* |
| + * IMG pixel format for the entire/overall image, e.g. |
| + * IMG_PIXFMT_B8G8R8A8_UNORM or IMG_PIXFMT_YUV420_2PLANE. |
| + */ |
| + IMG_PIXFMT eIMGPixelFormat; |
| + |
| + /* |
| + * DRI fourcc for the entire/overall image (defined by dri_interface.h), |
| + * e.g. __DRI_IMAGE_FOURCC_ARGB8888 or __DRI_IMAGE_FOURCC_NV12. |
| + */ |
| + int iDRIFourCC; |
| + |
| + /* |
| + * DRI format for the entire/overall image (defined by dri_interface.h), |
| + * e.g. __DRI_IMAGE_FORMAT_ARGB8888. This isn't applicable for YUV |
| + * formats and should be set to __DRI_IMAGE_FORMAT_NONE. |
| + */ |
| + int iDRIFormat; |
| + |
| + /* |
| + * DRI components for the entire/overall image (defined by |
| + * dri_interface.h), e.g. __DRI_IMAGE_COMPONENTS_RGBA or |
| + * __DRI_IMAGE_COMPONENTS_Y_UV. |
| + * |
| + * This specifies the image components and their groupings, in terms of |
| + * sub-images/planes, but not the order in which they appear. |
| + * |
| + * For example: |
| + * - any combination of BGRA channels would correspond to |
| + * __DRI_IMAGE_COMPONENTS_RGBA |
| + * - any combination of BGR or BGRX would correspond to |
| + * __DRI_IMAGE_COMPONENTS_RGB |
| + * - any combination of YUV with 2 planes would correspond to |
| + * __DRI_IMAGE_COMPONENTS_Y_UV |
| + */ |
| + int iDRIComponents; |
| + |
| + /* The number of sub-images/planes that make up the overall image */ |
| + unsigned uiNumPlanes; |
| + |
| + /* Per-plane information */ |
| + struct |
| + { |
| + /* |
| + * This is the amount that the image width should be bit-shifted |
| + * in order to give the plane width. This value can be determined |
| + * from the YUV sub-sampling ratios and should either be 0 (full |
| + * width), 1 (half width) or 2 (quarter width). |
| + */ |
| + unsigned int uiWidthShift; |
| + |
| + /* |
| + * This is the amount that the image height should be bit-shifted |
| + * in order to give the plane height. This value can be determined |
| + * from the YUV sub-sampling ratios and should either be 0 (full |
| + * height) or 1 (half height). |
| + */ |
| + unsigned int uiHeightShift; |
| + } sPlanes[DRI_PLANES_MAX]; |
| +} PVRDRIImageFormat; |
| + |
| + |
| +/*************************************************************************/ /*! |
| + pvrdri.c |
| +*/ /**************************************************************************/ |
| + |
| +void PVRDRIDrawableLock(PVRDRIDrawable *psPVRDrawable); |
| +void PVRDRIDrawableUnlock(PVRDRIDrawable *psPVRDrawable); |
| + |
| +void PVRDRIScreenLock(PVRDRIScreen *psPVRScreen); |
| +void PVRDRIScreenUnlock(PVRDRIScreen *psPVRScreen); |
| + |
| +PVRDRIScreen *PVRDRIThreadGetCurrentScreen(void); |
| +void PVRDRIThreadSetCurrentScreen(PVRDRIScreen *psPVRScreen); |
| + |
| +bool PVRDRIFlushBuffersForSwap(PVRDRIContext *psPVRContext, |
| + PVRDRIDrawable *psPVRDrawable); |
| + |
| + |
| +/*************************************************************************/ /*! |
| + pvrutil.c |
| +*/ /**************************************************************************/ |
| + |
| +void __attribute__((format(printf, 1, 2))) __driUtilMessage(const char *f, ...); |
| +void __attribute__((format(printf, 1, 2))) errorMessage(const char *f, ...); |
| + |
| +const __DRIconfig **PVRDRICreateConfigs(void); |
| + |
| +const PVRDRIImageFormat *PVRDRIFormatToImageFormat(int iDRIFormat); |
| +const PVRDRIImageFormat *PVRDRIFourCCToImageFormat(int iDRIFourCC); |
| +const PVRDRIImageFormat *PVRDRIIMGPixelFormatToImageFormat(IMG_PIXFMT eIMGPixelFormat); |
| + |
| +IMG_YUV_COLORSPACE PVRDRIToIMGColourSpace(const PVRDRIImageFormat *psFormat, |
| + enum __DRIYUVColorSpace eDRIColourSpace, |
| + enum __DRISampleRange eDRISampleRange); |
| +IMG_YUV_CHROMA_INTERP PVRDRIChromaSittingToIMGInterp(const PVRDRIImageFormat *psFormat, |
| + enum __DRIChromaSiting eChromaSitting); |
| + |
| + |
| +/*************************************************************************/ /*! |
| + pvrdrawable.c |
| +*/ /**************************************************************************/ |
| + |
| +bool PVRDRIDrawableInit(PVRDRIDrawable *psPVRDrawable); |
| +void PVRDRIDrawableDeinit(PVRDRIDrawable *psPVRDrawable); |
| + |
| +/* Callbacks into non-impl layer */ |
| +bool PVRDRIDrawableUpdateNativeInfo(PVRDRIDrawable *psPVRDrawable); |
| +bool PVRDRIDrawableRecreate(PVRDRIDrawable *psPVRDrawable); |
| +bool PVRDRIDrawableGetParameters(PVRDRIDrawable *psPVRDrawable, |
| + PVRDRIBufferImpl **ppsDstBuffer, |
| + PVRDRIBufferImpl **ppsAccumBuffer, |
| + PVRDRIBufferAttribs *psAttribs, |
| + bool *pbDoubleBuffered); |
| + |
| + |
| +/*************************************************************************/ /*! |
| + pvrimage.c |
| +*/ /**************************************************************************/ |
| + |
| +__DRIimage *PVRDRIScreenGetDRIImage(void *hEGLImage); |
| +void PVRDRIRefImage(__DRIimage *image); |
| +void PVRDRIUnrefImage(__DRIimage *image); |
| + |
| +/* Callbacks into non-impl layer */ |
| +PVRDRIImageType PVRDRIImageGetSharedType(__DRIimage *image); |
| +PVRDRIBufferImpl *PVRDRIImageGetSharedBuffer(__DRIimage *image); |
| +IMGEGLImage *PVRDRIImageGetSharedEGLImage(__DRIimage *image); |
| +IMGEGLImage *PVRDRIImageGetEGLImage(__DRIimage *image); |
| + |
| +#endif /* defined(__PVRDRI2_H__) */ |
| diff --git a/src/mesa/drivers/dri/pvr/pvrext.c b/src/mesa/drivers/dri/pvr/pvrext.c |
| new file mode 100644 |
| index 0000000..877e23f |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrext.c |
| @@ -0,0 +1,388 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/* |
| + * Copyright (c) Imagination Technologies Ltd. |
| + * |
| + * The contents of this file are subject to the MIT license as set out below. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +/* |
| + * EXTENSION SUPPORT |
| + * |
| + * As the driver supports a range of Mesa versions it can be the case that it |
| + * needs to support different extensions and extension versions depending on |
| + * the version of Mesa that it's built against. As a guide the following rules |
| + * should be followed: |
| + * |
| + * 1) If an extension appears in some supported versions of Mesa but not others |
| + * then it should be protected by the extension define, e.g.: |
| + * #if defined(__DRI_IMAGE) |
| + * <code> |
| + * #endif |
| + * |
| + * However, if it appears in all versions then there's no need for it to |
| + * be protected. |
| + * |
| + * 2) Each driver supported extension should have a define for the maximum |
| + * version supported by the driver. This should be used when initialising |
| + * the corresponding extension structure. The Mesa extension version define |
| + * should *NOT* be used. |
| + * |
| + * 3) If the driver supports a range of versions for a given extension then |
| + * it should protect the extension code based on the Mesa extension version |
| + * define. For example, if the driver has to support versions 7 to 8 of the |
| + * __DRI_IMAGE extension then any fields, in the __DRIimageExtension |
| + * structure, that appear in version 8 but not 7 should be protected as |
| + * follows: |
| + * #if (__DRI_IMAGE_VERSION >= 8) |
| + * .createImageFromDmaBufs = PVRDRICreateImageFromDmaBufs, |
| + * #endif |
| + * |
| + * Obviously any other associated code should also be protected in the same |
| + * way. |
| + */ |
| + |
| +#include "dri_util.h" |
| + |
| +#include "pvrdri.h" |
| +#include "pvrimage.h" |
| + |
| +#include "EGL/egl.h" |
| +#include "EGL/eglext.h" |
| +#include "powervr/dri_support.h" |
| + |
| +/* Maximum version numbers for each supported extension */ |
| +#define PVR_DRI_TEX_BUFFER_VERSION 2 |
| +#define PVR_DRI2_FLUSH_VERSION 4 |
| +#define PVR_DRI_IMAGE_VERSION 8 |
| +#define PVR_DRI2_ROBUSTNESS_VERSION 1 |
| +#define PVR_DRI_PRIORITY_VERSION 1 |
| +#define PVR_DRI2_FENCE_VERSION 1 |
| + |
| +/* |
| + * The bFlushInProgress flag is intended to prevent new buffers being fetched |
| + * whilst a flush is in progress, which may corrupt the state maintained by |
| + * the Mesa platform code. |
| + */ |
| +static void inline |
| +PVRDRILockBeforeFlush(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRDRIDrawableLock(psPVRDrawable); |
| + psPVRDrawable->bFlushInProgress = true; |
| +} |
| + |
| +static void inline |
| +PVRDRIUnlockAfterFlush(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + psPVRDrawable->bFlushInProgress = false; |
| + PVRDRIDrawableUnlock(psPVRDrawable); |
| +} |
| + |
| +static void inline |
| +PVRDRIInvalidateAndUnlockAfterFlush(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + /* Force a query for new buffers */ |
| + psPVRDrawable->bDrawableInfoInvalid = true; |
| + psPVRDrawable->bDrawableInfoUpdated = false; |
| + |
| + PVRDRIUnlockAfterFlush(psPVRDrawable); |
| +} |
| + |
| +static void PVRDRIFlushAllContexts(PVRDRIDrawable *psPVRDrawable) |
| +{ |
| + PVRQElem *psQElem; |
| + |
| + PVRDRILockBeforeFlush(psPVRDrawable); |
| + psQElem = psPVRDrawable->sPVRContextHead.pvForw; |
| + |
| + while (psQElem != &psPVRDrawable->sPVRContextHead) |
| + { |
| + PVRDRIContext *psPVRContext = PVRQ_CONTAINER_OF(psQElem, PVRDRIContext, sQElem); |
| + PVRDRIEGLFlushBuffers(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + psPVRDrawable->psImpl, |
| + false, |
| + false, |
| + false); |
| + psQElem = psPVRContext->sQElem.pvForw; |
| + } |
| + |
| + PVRDRIUnlockAfterFlush(psPVRDrawable); |
| +} |
| + |
| +static void PVRDRIExtSetTexBuffer(__DRIcontext *psDRIContext, |
| + GLint target, |
| + GLint format, |
| + __DRIdrawable *psDRIDrawable) |
| +{ |
| + PVRDRIDrawable *psPVRDrawable = (PVRDRIDrawable *)psDRIDrawable->driverPrivate; |
| + PVRDRIContext *psPVRContext = (PVRDRIContext *)psDRIContext->driverPrivate; |
| + |
| + (void)target; |
| + (void)format; |
| + |
| + if (!psPVRDrawable->bInitialised) |
| + { |
| + if (!PVRDRIDrawableInit(psPVRDrawable)) |
| + { |
| + __driUtilMessage("%s: Couldn't initialise pixmap", __func__); |
| + return; |
| + } |
| + } |
| + |
| + PVRDRIFlushAllContexts(psPVRDrawable); |
| + PVRDRI2BindTexImage(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + psPVRDrawable->psImpl); |
| +} |
| + |
| +static void PVRDRIExtReleaseTexBuffer(__DRIcontext *psDRIContext, |
| + GLint target, |
| + __DRIdrawable *psDRIDrawable) |
| +{ |
| + PVRDRIDrawable *psPVRDrawable = (PVRDRIDrawable *)psDRIDrawable->driverPrivate; |
| + PVRDRIContext *psPVRContext = (PVRDRIContext *)psDRIContext->driverPrivate; |
| + |
| + (void)target; |
| + |
| + PVRDRI2ReleaseTexImage(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + psPVRDrawable->psImpl); |
| +} |
| + |
| +static __DRItexBufferExtension pvrDRITexBufferExtension = |
| +{ |
| + .base = { .name = __DRI_TEX_BUFFER, .version = PVR_DRI_TEX_BUFFER_VERSION }, |
| + .setTexBuffer = NULL, |
| + .setTexBuffer2 = PVRDRIExtSetTexBuffer, |
| + .releaseTexBuffer = PVRDRIExtReleaseTexBuffer |
| +}; |
| + |
| + |
| +static void PVRDRI2Flush(__DRIdrawable *psDRIDrawable) |
| +{ |
| + PVRDRIDrawable *psPVRDrawable = (PVRDRIDrawable *)psDRIDrawable->driverPrivate; |
| + |
| + PVRDRILockBeforeFlush(psPVRDrawable); |
| + |
| + (void) PVRDRIFlushBuffersForSwap(NULL, psPVRDrawable); |
| + |
| + PVRDRIInvalidateAndUnlockAfterFlush(psPVRDrawable); |
| +} |
| + |
| +static void PVRDRI2Invalidate(__DRIdrawable *psDRIDrawable) |
| +{ |
| + PVRDRIDrawable *psPVRDrawable = (PVRDRIDrawable *)psDRIDrawable->driverPrivate; |
| + |
| + if (psPVRDrawable->psPVRScreen->bUseInvalidate) |
| + { |
| + PVRDRIDrawableLock(psPVRDrawable); |
| + psPVRDrawable->bDrawableInfoInvalid = true; |
| + psPVRDrawable->bDrawableInfoUpdated = false; |
| + PVRDRIDrawableUnlock(psPVRDrawable); |
| + } |
| +} |
| + |
| +static void PVRDRI2FlushWithFlags(__DRIcontext *psDRIContext, |
| + __DRIdrawable *psDRIDrawable, |
| + unsigned uFlags, |
| + enum __DRI2throttleReason eThrottleReason) |
| +{ |
| + PVRDRIContext *psPVRContext = (PVRDRIContext *)psDRIContext->driverPrivate; |
| + |
| + (void)eThrottleReason; |
| + |
| + if ((uFlags & __DRI2_FLUSH_DRAWABLE) != 0) |
| + { |
| + PVRDRIDrawable *psPVRDrawable = (PVRDRIDrawable *) psDRIDrawable->driverPrivate; |
| + |
| + PVRDRILockBeforeFlush(psPVRDrawable); |
| + |
| + (void) PVRDRIFlushBuffersForSwap(psPVRContext, psPVRDrawable); |
| + |
| + PVRDRIInvalidateAndUnlockAfterFlush(psPVRDrawable); |
| + } |
| + else if ((uFlags & __DRI2_FLUSH_CONTEXT) != 0) |
| + { |
| + (void) PVRDRIEGLFlushBuffers(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + NULL, true, false, false); |
| + } |
| +} |
| + |
| +static __DRI2flushExtension pvrDRI2FlushExtension = |
| +{ |
| + .base = { .name = __DRI2_FLUSH, .version = PVR_DRI2_FLUSH_VERSION }, |
| + .flush = PVRDRI2Flush, |
| + .invalidate = PVRDRI2Invalidate, |
| + .flush_with_flags = PVRDRI2FlushWithFlags, |
| +}; |
| + |
| + |
| +static __DRIimageExtension pvrDRIImage = |
| +{ |
| + .base = { .name = __DRI_IMAGE, .version = PVR_DRI_IMAGE_VERSION }, |
| + .createImageFromName = PVRDRICreateImageFromName, |
| + .createImageFromRenderbuffer = PVRDRICreateImageFromRenderbuffer, |
| + .destroyImage = PVRDRIDestroyImage, |
| + .createImage = PVRDRICreateImage, |
| + .queryImage = PVRDRIQueryImage, |
| + .dupImage = PVRDRIDupImage, |
| + .validateUsage = PVRDRIValidateUsage, |
| + .createImageFromNames = PVRDRICreateImageFromNames, |
| + .fromPlanar = PVRDRIFromPlanar, |
| + .createImageFromTexture = PVRDRICreateImageFromTexture, |
| + .createImageFromFds = PVRDRICreateImageFromFds, |
| +#if defined(EGL_IMG_cl_image) |
| + .createImageFromBuffer = PVRDRICreateImageFromBuffer, |
| +#endif |
| + .createImageFromDmaBufs = PVRDRICreateImageFromDmaBufs, |
| +}; |
| + |
| +static __DRIrobustnessExtension pvrDRIRobustness = |
| +{ |
| + .base = { .name = __DRI2_ROBUSTNESS, .version = PVR_DRI2_ROBUSTNESS_VERSION } |
| +}; |
| + |
| +#if defined(__DRI_PRIORITY) |
| +static __DRIpriorityExtension pvrDRIPriority = |
| +{ |
| + .base = { .name = __DRI_PRIORITY, .version = PVR_DRI_PRIORITY_VERSION } |
| +}; |
| +#endif /* defined(__DRI_PRIORITY) */ |
| + |
| + |
| +#if defined(__DRI2_FENCE) |
| +static void *PVRDRICreateFenceEXT(__DRIcontext *psDRIContext) |
| +{ |
| + PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; |
| + PVRDRIScreen *psPVRScreen = psPVRContext->psPVRScreen; |
| + |
| + return PVRDRICreateFenceImpl(psPVRContext->eAPI, |
| + psPVRScreen->psImpl, |
| + psPVRContext->psImpl); |
| +} |
| + |
| +static void PVRDRIDestroyFenceEXT(__DRIscreen *psDRIScreen, void *psDRIFence) |
| +{ |
| + (void)psDRIScreen; |
| + |
| + PVRDRIDestroyFenceImpl(psDRIFence); |
| +} |
| + |
| +static GLboolean PVRDRIClientWaitSyncEXT(__DRIcontext *psDRIContext, |
| + void *psDRIFence, |
| + unsigned uFlags, |
| + uint64_t uiTimeout) |
| +{ |
| + bool bFlushCommands = (uFlags & __DRI2_FENCE_FLAG_FLUSH_COMMANDS); |
| + bool bTimeout = (uiTimeout != __DRI2_FENCE_TIMEOUT_INFINITE); |
| + PVRDRIAPIType eAPI = 0; |
| + PVRDRIContextImpl *psImpl = NULL; |
| + |
| + if (psDRIContext) |
| + { |
| + PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; |
| + |
| + eAPI = psPVRContext->eAPI; |
| + psImpl = psPVRContext->psImpl; |
| + } |
| + |
| + return PVRDRIClientWaitSyncImpl(eAPI, |
| + psImpl, |
| + psDRIFence, |
| + bFlushCommands, |
| + bTimeout, |
| + uiTimeout); |
| +} |
| + |
| +static void PVRDRIServerWaitSyncEXT(__DRIcontext *psDRIContext, |
| + void *psDRIFence, |
| + unsigned uFlags) |
| +{ |
| + (void)uFlags; |
| + assert(uFlags == 0); |
| + |
| + if (psDRIFence) |
| + { |
| + PVRDRIContext *psPVRContext = psDRIContext->driverPrivate; |
| + |
| + if (!PVRDRIServerWaitSyncImpl(psPVRContext->eAPI, |
| + psPVRContext->psImpl, |
| + psDRIFence)) |
| + { |
| + __driUtilMessage("%s: Server wait sync failed", |
| + __func__); |
| + } |
| + } |
| +} |
| + |
| +const __DRI2fenceExtension pvrDRIFenceExtension = |
| +{ |
| + .base = { .name = __DRI2_FENCE, .version = PVR_DRI2_FENCE_VERSION }, |
| + .create_fence = PVRDRICreateFenceEXT, |
| + /* Not currently supported */ |
| + .get_fence_from_cl_event = NULL, |
| + .destroy_fence = PVRDRIDestroyFenceEXT, |
| + .client_wait_sync = PVRDRIClientWaitSyncEXT, |
| + .server_wait_sync = PVRDRIServerWaitSyncEXT, |
| +}; |
| +#endif /* defined(__DRI2_FENCE) */ |
| + |
| +/* |
| + * Extension lists |
| + * |
| + * NOTE: When adding a new screen extension asScreenExtensionVersionInfo |
| + * should also be updated accordingly. |
| + */ |
| +const __DRIextension *apsScreenExtensions[] = |
| +{ |
| + &pvrDRITexBufferExtension.base, |
| + &pvrDRI2FlushExtension.base, |
| + &pvrDRIImage.base, |
| + &pvrDRIRobustness.base, |
| +#if defined(__DRI_PRIORITY) |
| + &pvrDRIPriority.base, |
| +#endif |
| +#if defined(__DRI2_FENCE) |
| + &pvrDRIFenceExtension.base, |
| +#endif |
| + NULL |
| +}; |
| + |
| +const __DRIextension asScreenExtensionVersionInfo[] = |
| +{ |
| + { .name = __DRI_TEX_BUFFER, .version = __DRI_TEX_BUFFER_VERSION }, |
| + { .name = __DRI2_FLUSH, .version = __DRI2_FLUSH_VERSION }, |
| + { .name = __DRI_IMAGE, .version = __DRI_IMAGE_VERSION }, |
| + { .name = __DRI2_ROBUSTNESS, .version = __DRI2_ROBUSTNESS_VERSION }, |
| +#if defined(__DRI_PRIORITY) |
| + { .name = __DRI_PRIORITY, .version = __DRI_PRIORITY_VERSION }, |
| +#endif |
| +#if defined(__DRI2_FENCE) |
| + { .name = __DRI2_FENCE, .version = __DRI2_FENCE_VERSION }, |
| +#endif |
| + { .name = NULL, .version = 0 }, |
| +}; |
| diff --git a/src/mesa/drivers/dri/pvr/pvrimage.c b/src/mesa/drivers/dri/pvr/pvrimage.c |
| new file mode 100644 |
| index 0000000..8bd8057 |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrimage.c |
| @@ -0,0 +1,1042 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/* |
| + * Copyright (c) Imagination Technologies Ltd. |
| + * |
| + * The contents of this file are subject to the MIT license as set out below. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#include <assert.h> |
| +#include <xf86drm.h> |
| + |
| +#include "dri_util.h" |
| + |
| +#include "pvrdri.h" |
| +#include "pvrimage.h" |
| +#include "EGL/egl.h" |
| +#include "EGL/eglext.h" |
| + |
| +struct PVRDRIImageShared |
| +{ |
| + int iRefCount; |
| + |
| + PVRDRIScreen *psPVRScreen; |
| + |
| + PVRDRIImageType eType; |
| + const PVRDRIImageFormat *psFormat; |
| + IMG_YUV_COLORSPACE eColourSpace; |
| + IMG_YUV_CHROMA_INTERP eChromaUInterp; |
| + IMG_YUV_CHROMA_INTERP eChromaVInterp; |
| + |
| + PVRDRIBufferImpl *psBuffer; |
| + IMGEGLImage *psEGLImage; |
| + PVRDRIEGLImageType eglImageType; |
| +}; |
| + |
| +struct __DRIimageRec |
| +{ |
| + int iRefCount; |
| + |
| + void *loaderPrivate; |
| + |
| + struct PVRDRIImageShared *psShared; |
| + |
| + IMGEGLImage *psEGLImage; |
| +}; |
| + |
| + |
| +static struct PVRDRIImageShared * |
| +CommonImageSharedSetup(PVRDRIImageType eType, |
| + __DRIscreen *screen) |
| +{ |
| + struct PVRDRIImageShared *shared; |
| + |
| + shared = calloc(1, sizeof(*shared)); |
| + if (!shared) |
| + { |
| + return NULL; |
| + } |
| + |
| + shared->psPVRScreen = DRIScreenPrivate(screen); |
| + shared->eType = eType; |
| + shared->iRefCount = 1; |
| + |
| + assert(shared->eColourSpace == IMG_COLORSPACE_UNDEFINED && |
| + shared->eChromaUInterp == IMG_CHROMA_INTERP_UNDEFINED && |
| + shared->eChromaVInterp == IMG_CHROMA_INTERP_UNDEFINED); |
| + |
| + return shared; |
| +} |
| + |
| +static void DestroyImageShared(struct PVRDRIImageShared *shared) |
| +{ |
| + int iRefCount = __sync_sub_and_fetch(&shared->iRefCount, 1); |
| + |
| + assert(iRefCount >= 0); |
| + |
| + if (iRefCount > 0) |
| + { |
| + return; |
| + } |
| + |
| + switch (shared->eType) |
| + { |
| + case PVRDRI_IMAGE_FROM_NAMES: |
| + case PVRDRI_IMAGE_FROM_DMABUFS: |
| + case PVRDRI_IMAGE: |
| + if (shared->psBuffer) |
| + { |
| + PVRDRIBufferDestroy(shared->psBuffer); |
| + } |
| + break; |
| + case PVRDRI_IMAGE_FROM_EGLIMAGE: |
| + PVRDRIEGLImageDestroyExternal(shared->psPVRScreen->psImpl, |
| + shared->psEGLImage, |
| + shared->eglImageType); |
| + break; |
| + default: |
| + errorMessage("%s: Unknown image type: %d\n", __func__, (int)shared->eType); |
| + break; |
| + } |
| + |
| + free(shared); |
| +} |
| + |
| +static struct PVRDRIImageShared * |
| +CreateImageSharedFromEGLImage(__DRIscreen *screen, |
| + IMGEGLImage *psEGLImage, |
| + PVRDRIEGLImageType eglImageType) |
| +{ |
| + struct PVRDRIImageShared *shared; |
| + PVRDRIBufferAttribs sAttribs; |
| + const PVRDRIImageFormat *psFormat; |
| + |
| + PVRDRIEGLImageGetAttribs(psEGLImage, &sAttribs); |
| + |
| + psFormat = PVRDRIIMGPixelFormatToImageFormat(sAttribs.ePixFormat); |
| + if (!psFormat) |
| + { |
| + return NULL; |
| + } |
| + |
| + shared = CommonImageSharedSetup(PVRDRI_IMAGE_FROM_EGLIMAGE, screen); |
| + if (!shared) |
| + { |
| + return NULL; |
| + } |
| + |
| + shared->psEGLImage = psEGLImage; |
| + shared->psFormat = psFormat; |
| + shared->eglImageType = eglImageType; |
| + |
| + return shared; |
| +} |
| + |
| +static struct PVRDRIImageShared * |
| +CreateImageSharedFromNames(__DRIscreen *screen, |
| + int width, |
| + int height, |
| + int fourcc, |
| + int *names, |
| + int num_names, |
| + int *strides, |
| + int *offsets) |
| +{ |
| + struct PVRDRIImageShared *shared; |
| + const PVRDRIImageFormat *psFormat; |
| + unsigned auiWidthShift[DRI_PLANES_MAX]; |
| + unsigned auiHeightShift[DRI_PLANES_MAX]; |
| + int i; |
| + |
| + psFormat = PVRDRIFourCCToImageFormat(fourcc); |
| + if (!psFormat) |
| + { |
| + errorMessage("%s: Unsupported DRI FourCC (fourcc = 0x%X)\n", |
| + __func__, fourcc); |
| + return NULL; |
| + } |
| + |
| + if (psFormat->uiNumPlanes < num_names) |
| + { |
| + errorMessage("%s: Unexpected number of names for DRI FourCC (names = %d, fourcc = 0x%X)\n", |
| + __func__, num_names, fourcc); |
| + return NULL; |
| + } |
| + |
| + for (i = 0; i < num_names; i++) |
| + { |
| + if (offsets[i] < 0) |
| + { |
| + errorMessage("%s: Offset %d unsupported (value = %d)\n", |
| + __func__, i, offsets[i]); |
| + return NULL; |
| + } |
| + |
| + auiWidthShift[i] = psFormat->sPlanes[i].uiWidthShift; |
| + auiHeightShift[i] = psFormat->sPlanes[i].uiHeightShift; |
| + } |
| + |
| + shared = CommonImageSharedSetup(PVRDRI_IMAGE_FROM_NAMES, screen); |
| + if (!shared) |
| + { |
| + return NULL; |
| + } |
| + |
| + shared->psBuffer = PVRDRIBufferCreateFromNames(shared->psPVRScreen->psImpl, |
| + width, |
| + height, |
| + num_names, |
| + names, |
| + strides, |
| + offsets, |
| + auiWidthShift, |
| + auiHeightShift); |
| + |
| + if (!shared->psBuffer) |
| + { |
| + errorMessage("%s: Failed to create buffer for shared image\n", __func__); |
| + goto ErrorDestroyImage; |
| + } |
| + |
| + shared->psFormat = psFormat; |
| + shared->eColourSpace = |
| + PVRDRIToIMGColourSpace(psFormat, |
| + __DRI_YUV_COLOR_SPACE_UNDEFINED, |
| + __DRI_YUV_RANGE_UNDEFINED); |
| + shared->eChromaUInterp = |
| + PVRDRIChromaSittingToIMGInterp(psFormat, |
| + __DRI_YUV_CHROMA_SITING_UNDEFINED); |
| + shared->eChromaVInterp = |
| + PVRDRIChromaSittingToIMGInterp(psFormat, |
| + __DRI_YUV_CHROMA_SITING_UNDEFINED); |
| + |
| + return shared; |
| + |
| +ErrorDestroyImage: |
| + DestroyImageShared(shared); |
| + |
| + return NULL; |
| +} |
| + |
| +static struct PVRDRIImageShared * |
| +CreateImageSharedFromDmaBufs(__DRIscreen *screen, |
| + int width, |
| + int height, |
| + int fourcc, |
| + int *fds, |
| + int num_fds, |
| + int *strides, |
| + int *offsets, |
| + enum __DRIYUVColorSpace color_space, |
| + enum __DRISampleRange sample_range, |
| + enum __DRIChromaSiting horiz_siting, |
| + enum __DRIChromaSiting vert_siting, |
| + unsigned *error) |
| +{ |
| + struct PVRDRIImageShared *shared; |
| + const PVRDRIImageFormat *psFormat; |
| + unsigned auiWidthShift[DRI_PLANES_MAX]; |
| + unsigned auiHeightShift[DRI_PLANES_MAX]; |
| + int i; |
| + |
| + psFormat = PVRDRIFourCCToImageFormat(fourcc); |
| + if (!psFormat) |
| + { |
| + errorMessage("%s: Unsupported DRI FourCC (fourcc = 0x%X)\n", |
| + __func__, fourcc); |
| + *error = __DRI_IMAGE_ERROR_BAD_MATCH; |
| + return NULL; |
| + } |
| + |
| + if (psFormat->uiNumPlanes < num_fds) |
| + { |
| + errorMessage("%s: Unexpected number of fds for format (fds = %d, fourcc = 0x%X)\n", |
| + __func__, num_fds, fourcc); |
| + *error = __DRI_IMAGE_ERROR_BAD_MATCH; |
| + return NULL; |
| + } |
| + |
| + for (i = 0; i < num_fds; i++) |
| + { |
| + if (offsets[i] < 0) |
| + { |
| + errorMessage("%s: Offset %d unsupported (value = %d)\n", |
| + __func__, i, offsets[i]); |
| + *error = __DRI_IMAGE_ERROR_BAD_ACCESS; |
| + return NULL; |
| + } |
| + |
| + auiWidthShift[i] = psFormat->sPlanes[i].uiWidthShift; |
| + auiHeightShift[i] = psFormat->sPlanes[i].uiHeightShift; |
| + } |
| + |
| + shared = CommonImageSharedSetup(PVRDRI_IMAGE_FROM_DMABUFS, screen); |
| + if (!shared) |
| + { |
| + *error = __DRI_IMAGE_ERROR_BAD_ALLOC; |
| + return NULL; |
| + } |
| + |
| + shared->psBuffer = PVRDRIBufferCreateFromFds(shared->psPVRScreen->psImpl, |
| + width, |
| + height, |
| + num_fds, |
| + fds, |
| + strides, |
| + offsets, |
| + auiWidthShift, |
| + auiHeightShift); |
| + |
| + if (!shared->psBuffer) |
| + { |
| + errorMessage("%s: Failed to create buffer for shared image\n", __func__); |
| + *error = __DRI_IMAGE_ERROR_BAD_ALLOC; |
| + goto ErrorDestroyImage; |
| + } |
| + |
| + shared->psFormat = psFormat; |
| + shared->eColourSpace = PVRDRIToIMGColourSpace(psFormat, color_space, sample_range); |
| + shared->eChromaUInterp = PVRDRIChromaSittingToIMGInterp(psFormat, horiz_siting); |
| + shared->eChromaVInterp = PVRDRIChromaSittingToIMGInterp(psFormat, vert_siting); |
| + |
| + return shared; |
| + |
| +ErrorDestroyImage: |
| + DestroyImageShared(shared); |
| + |
| + return NULL; |
| +} |
| + |
| +static struct PVRDRIImageShared * |
| +CreateImageShared(__DRIscreen *screen, |
| + int width, |
| + int height, |
| + int format, |
| + unsigned int use, |
| + int *piStride) |
| +{ |
| + struct PVRDRIImageShared *shared; |
| + const PVRDRIImageFormat *psFormat; |
| + unsigned int uiStride; |
| + |
| + if ((use & __DRI_IMAGE_USE_CURSOR) && (use & __DRI_IMAGE_USE_SCANOUT)) |
| + { |
| + return NULL; |
| + } |
| + |
| + psFormat = PVRDRIFormatToImageFormat(format); |
| + if (!psFormat) |
| + { |
| + errorMessage("%s: Unsupported DRI image format (format = 0x%X)\n", |
| + __func__, format); |
| + return NULL; |
| + } |
| + |
| + shared = CommonImageSharedSetup(PVRDRI_IMAGE, screen); |
| + if (!shared) |
| + { |
| + return NULL; |
| + } |
| + |
| + shared->psBuffer = |
| + PVRDRIBufferCreate(shared->psPVRScreen->psImpl, |
| + width, |
| + height, |
| + PVRDRIPixFmtGetBPP(psFormat->eIMGPixelFormat), |
| + use, |
| + &uiStride); |
| + if (!shared->psBuffer) |
| + { |
| + errorMessage("%s: Failed to create buffer\n", __func__); |
| + goto ErrorDestroyImage; |
| + } |
| + |
| + shared->psFormat = psFormat; |
| + |
| + *piStride = uiStride; |
| + |
| + return shared; |
| + |
| +ErrorDestroyImage: |
| + DestroyImageShared(shared); |
| + |
| + return NULL; |
| +} |
| + |
| +static struct PVRDRIImageShared *RefImageShared(struct PVRDRIImageShared *shared) |
| +{ |
| + int iRefCount = __sync_fetch_and_add(&shared->iRefCount, 1); |
| + |
| + (void)iRefCount; |
| + assert(iRefCount > 0); |
| + |
| + return shared; |
| +} |
| + |
| +static __DRIimage *CommonImageSetup(void *loaderPrivate) |
| +{ |
| + __DRIimage *image; |
| + |
| + image = calloc(1, sizeof(*image)); |
| + if (!image) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->loaderPrivate = loaderPrivate; |
| + image->iRefCount = 1; |
| + |
| + return image; |
| +} |
| + |
| +void PVRDRIDestroyImage(__DRIimage *image) |
| +{ |
| + int iRefCount = __sync_sub_and_fetch(&image->iRefCount, 1); |
| + |
| + assert(iRefCount >= 0); |
| + |
| + if (iRefCount > 0) |
| + { |
| + return; |
| + } |
| + |
| + if (image->psShared) |
| + { |
| + DestroyImageShared(image->psShared); |
| + } |
| + |
| + PVRDRIEGLImageFree(image->psEGLImage); |
| + |
| + free(image); |
| +} |
| + |
| +__DRIimage *PVRDRICreateImageFromName(__DRIscreen *screen, |
| + int width, int height, int format, |
| + int name, int pitch, |
| + void *loaderPrivate) |
| +{ |
| + const PVRDRIImageFormat *psFormat; |
| + int iStride; |
| + int iOffset; |
| + |
| + psFormat = PVRDRIFormatToImageFormat(format); |
| + if (!psFormat) |
| + { |
| + errorMessage("%s: Unsupported DRI image format (format = 0x%X)\n", |
| + __func__, format); |
| + return NULL; |
| + } |
| + |
| + iStride = pitch * PVRDRIPixFmtGetBlockSize(psFormat->eIMGPixelFormat); |
| + iOffset = 0; |
| + |
| + return PVRDRICreateImageFromNames(screen, width, height, psFormat->iDRIFourCC, |
| + &name, 1, &iStride, &iOffset, loaderPrivate); |
| +} |
| + |
| +__DRIimage *PVRDRICreateImageFromRenderbuffer(__DRIcontext *context, |
| + int renderbuffer, |
| + void *loaderPrivate) |
| +{ |
| + PVRDRIContext *psPVRContext = context->driverPrivate; |
| + __DRIscreen *screen = psPVRContext->psPVRScreen->psDRIScreen; |
| + unsigned e; |
| + IMGEGLImage *psEGLImage; |
| + __DRIimage *image; |
| + |
| + image = CommonImageSetup(loaderPrivate); |
| + if (!image) |
| + { |
| + return NULL; |
| + } |
| + |
| + psEGLImage = PVRDRIEGLImageCreate(); |
| + if (!psEGLImage) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + e = PVRDRIGetImageSource(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + EGL_GL_RENDERBUFFER_KHR, |
| + (uintptr_t)renderbuffer, |
| + 0, |
| + psEGLImage); |
| + |
| + if (e != PVRDRI_IMAGE_ERROR_SUCCESS) |
| + { |
| + PVRDRIEGLImageFree(psEGLImage); |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + PVRDRIEGLImageSetCallbackData(psEGLImage, image); |
| + |
| + /* |
| + * We can't destroy the image after this point, as the |
| + * renderbuffer now has a reference to it. |
| + */ |
| + image->psShared = CreateImageSharedFromEGLImage(screen, |
| + psEGLImage, |
| + PVRDRI_EGLIMAGE_IMGEGL); |
| + if (!image->psShared) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->psEGLImage = PVRDRIEGLImageDup(image->psShared->psEGLImage); |
| + if (!image->psEGLImage) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->iRefCount++; |
| + |
| + return image; |
| +} |
| + |
| +__DRIimage *PVRDRICreateImage(__DRIscreen *screen, |
| + int width, int height, int format, |
| + unsigned int use, |
| + void *loaderPrivate) |
| +{ |
| + __DRIimage *image; |
| + int iStride; |
| + |
| + image = CommonImageSetup(loaderPrivate); |
| + if (!image) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->psShared = CreateImageShared(screen, width, height, format, use, &iStride); |
| + if (!image->psShared) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + image->psEGLImage = PVRDRIEGLImageCreateFromBuffer(width, height, iStride, |
| + image->psShared->psFormat->eIMGPixelFormat, |
| + image->psShared->eColourSpace, |
| + image->psShared->eChromaUInterp, |
| + image->psShared->eChromaUInterp, |
| + image->psShared->psBuffer); |
| + if (!image->psEGLImage) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + PVRDRIEGLImageSetCallbackData(image->psEGLImage, image); |
| + |
| + return image; |
| +} |
| + |
| +GLboolean PVRDRIQueryImage(__DRIimage *image, int attrib, int *value_ptr) |
| +{ |
| + struct PVRDRIImageShared *shared = image->psShared; |
| + PVRDRIBufferAttribs sAttribs; |
| + int value; |
| + |
| + PVRDRIEGLImageGetAttribs(image->psEGLImage, &sAttribs); |
| + |
| + if (attrib == __DRI_IMAGE_ATTRIB_HANDLE || |
| + attrib == __DRI_IMAGE_ATTRIB_NAME || |
| + attrib == __DRI_IMAGE_ATTRIB_FD) |
| + { |
| + if (!shared->psFormat) |
| + { |
| + return GL_FALSE; |
| + } |
| + |
| + switch (shared->psFormat->iDRIComponents) |
| + { |
| + case __DRI_IMAGE_COMPONENTS_R: |
| + case __DRI_IMAGE_COMPONENTS_RG: |
| + case __DRI_IMAGE_COMPONENTS_RGB: |
| + case __DRI_IMAGE_COMPONENTS_RGBA: |
| + break; |
| + default: |
| + return GL_FALSE; |
| + } |
| + } |
| + |
| + switch (attrib) |
| + { |
| + case __DRI_IMAGE_ATTRIB_STRIDE: |
| + *value_ptr = sAttribs.uiStrideInBytes; |
| + break; |
| + case __DRI_IMAGE_ATTRIB_HANDLE: |
| + value = PVRDRIBufferGetHandle(shared->psBuffer); |
| + if (value == -1) |
| + { |
| + return GL_FALSE; |
| + } |
| + |
| + *value_ptr = value; |
| + break; |
| + case __DRI_IMAGE_ATTRIB_NAME: |
| + value = PVRDRIBufferGetName(shared->psBuffer); |
| + if (value == -1) |
| + { |
| + return GL_FALSE; |
| + } |
| + |
| + *value_ptr = value; |
| + break; |
| + case __DRI_IMAGE_ATTRIB_FORMAT: |
| + if (!shared->psFormat) |
| + { |
| + return GL_FALSE; |
| + } |
| + |
| + *value_ptr = shared->psFormat->iDRIFormat; |
| + break; |
| + case __DRI_IMAGE_ATTRIB_WIDTH: |
| + *value_ptr = sAttribs.uiWidth; |
| + break; |
| + case __DRI_IMAGE_ATTRIB_HEIGHT: |
| + *value_ptr = sAttribs.uiHeight; |
| + break; |
| + case __DRI_IMAGE_ATTRIB_COMPONENTS: |
| + if (!shared->psFormat || !shared->psFormat->iDRIComponents) |
| + { |
| + return GL_FALSE; |
| + } |
| + |
| + *value_ptr = shared->psFormat->iDRIComponents; |
| + break; |
| + case __DRI_IMAGE_ATTRIB_FD: |
| + value = PVRDRIBufferGetFd(shared->psBuffer); |
| + if (value == -1) |
| + { |
| + return GL_FALSE; |
| + } |
| + |
| + *value_ptr = value; |
| + break; |
| + default: |
| + return GL_FALSE; |
| + } |
| + |
| + return GL_TRUE; |
| +} |
| + |
| +__DRIimage *PVRDRIDupImage(__DRIimage *srcImage, void *loaderPrivate) |
| +{ |
| + __DRIimage *image; |
| + |
| + image = CommonImageSetup(loaderPrivate); |
| + if (!image) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->psShared = RefImageShared(srcImage->psShared); |
| + |
| + image->psEGLImage = PVRDRIEGLImageDup(srcImage->psEGLImage); |
| + if (!image->psEGLImage) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + PVRDRIEGLImageSetCallbackData(image->psEGLImage, image); |
| + |
| + return image; |
| +} |
| + |
| +GLboolean PVRDRIValidateUsage(__DRIimage *image, unsigned int use) |
| +{ |
| + __DRIscreen *screen = image->psShared->psPVRScreen->psDRIScreen; |
| + |
| + if (use & (__DRI_IMAGE_USE_SCANOUT | __DRI_IMAGE_USE_CURSOR)) |
| + { |
| + /* |
| + * We are extra strict in this case as an application may ask for a |
| + * handle so that the memory can be wrapped as a framebuffer/used as |
| + * a cursor and this can only be done on a card node. |
| + */ |
| + if (drmGetNodeTypeFromFd(screen->fd) != DRM_NODE_PRIMARY) |
| + { |
| + return GL_FALSE; |
| + } |
| + } |
| + else if (use & (__DRI_IMAGE_USE_SHARE)) |
| + { |
| + /* |
| + * We are less strict in this case as it's possible to share buffers |
| + * using prime (but not flink) on a render node so we only need to know |
| + * whether or not the fd belongs to the display. |
| + */ |
| + if (PVRDRIGetDeviceTypeFromFd(screen->fd) != PVRDRI_DEVICE_TYPE_DISPLAY) |
| + { |
| + return GL_FALSE; |
| + } |
| + } |
| + |
| + return GL_TRUE; |
| +} |
| + |
| +__DRIimage *PVRDRICreateImageFromNames(__DRIscreen *screen, |
| + int width, int height, int fourcc, |
| + int *names, int num_names, |
| + int *strides, int *offsets, |
| + void *loaderPrivate) |
| +{ |
| + __DRIimage *image; |
| + int iStride; |
| + |
| + image = CommonImageSetup(loaderPrivate); |
| + if (!image) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->psShared = CreateImageSharedFromNames(screen, width, height, fourcc, |
| + names, num_names, strides, offsets); |
| + if (!image->psShared) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + if (image->psShared->psFormat->uiNumPlanes == 1) |
| + { |
| + iStride = strides[0]; |
| + } |
| + else |
| + { |
| + iStride = width * PVRDRIPixFmtGetBlockSize(image->psShared->psFormat->eIMGPixelFormat); |
| + } |
| + |
| + image->psEGLImage = PVRDRIEGLImageCreateFromBuffer(width, height, |
| + iStride, |
| + image->psShared->psFormat->eIMGPixelFormat, |
| + image->psShared->eColourSpace, |
| + image->psShared->eChromaUInterp, |
| + image->psShared->eChromaVInterp, |
| + image->psShared->psBuffer); |
| + if (!image->psEGLImage) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + PVRDRIEGLImageSetCallbackData(image->psEGLImage, image); |
| + |
| + return image; |
| +} |
| + |
| +__DRIimage *PVRDRIFromPlanar(__DRIimage *image, int plane, |
| + void *loaderPrivate) |
| +{ |
| + if (plane != 0) |
| + { |
| + errorMessage("%s: plane %d not supported\n", __func__, plane); |
| + } |
| + |
| + return PVRDRIDupImage(image, loaderPrivate); |
| +} |
| + |
| +__DRIimage * |
| +PVRDRICreateImageFromTexture(__DRIcontext *context, |
| + int glTarget, |
| + unsigned texture, |
| + int depth, |
| + int level, |
| + unsigned *error, |
| + void *loaderPrivate) |
| +{ |
| + PVRDRIContext *psPVRContext = context->driverPrivate; |
| + __DRIscreen *screen = psPVRContext->psPVRScreen->psDRIScreen; |
| + IMGEGLImage *psEGLImage; |
| + __DRIimage *image; |
| + uint32_t eglTarget; |
| + unsigned e; |
| + |
| + switch (glTarget) |
| + { |
| + case GL_TEXTURE_2D: |
| + eglTarget = EGL_GL_TEXTURE_2D_KHR; |
| + break; |
| + case GL_TEXTURE_CUBE_MAP: |
| + eglTarget = EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + depth; |
| + break; |
| + default: |
| + errorMessage("%s: GL Target %d is not supported\n", __func__, glTarget); |
| + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; |
| + return NULL; |
| + } |
| + |
| + image = CommonImageSetup(loaderPrivate); |
| + if (!image) |
| + { |
| + return NULL; |
| + } |
| + |
| + psEGLImage = PVRDRIEGLImageCreate(); |
| + if (!psEGLImage) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + e = PVRDRIGetImageSource(psPVRContext->eAPI, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + eglTarget, |
| + (uintptr_t)texture, |
| + (uint32_t)level, |
| + psEGLImage); |
| + *error = e; |
| + |
| + if (e != PVRDRI_IMAGE_ERROR_SUCCESS) |
| + { |
| + PVRDRIEGLImageFree(psEGLImage); |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + PVRDRIEGLImageSetCallbackData(psEGLImage, image); |
| + |
| + /* |
| + * We can't destroy the image after this point, as the |
| + * texture now has a reference to it. |
| + */ |
| + image->psShared = CreateImageSharedFromEGLImage(screen, |
| + psEGLImage, |
| + PVRDRI_EGLIMAGE_IMGEGL); |
| + if (!image->psShared) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->psEGLImage = PVRDRIEGLImageDup(image->psShared->psEGLImage); |
| + if (!image->psEGLImage) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->iRefCount++; |
| + |
| + return image; |
| +} |
| + |
| +__DRIimage *PVRDRICreateImageFromFds(__DRIscreen *screen, |
| + int width, int height, int fourcc, |
| + int *fds, int num_fds, |
| + int *strides, int *offsets, |
| + void *loaderPrivate) |
| +{ |
| + unsigned error; |
| + |
| + return PVRDRICreateImageFromDmaBufs(screen, width, height, fourcc, |
| + fds, num_fds, strides, offsets, |
| + __DRI_YUV_COLOR_SPACE_UNDEFINED, |
| + __DRI_YUV_RANGE_UNDEFINED, |
| + __DRI_YUV_CHROMA_SITING_UNDEFINED, |
| + __DRI_YUV_CHROMA_SITING_UNDEFINED, |
| + &error, |
| + loaderPrivate); |
| +} |
| + |
| +__DRIimage * |
| +PVRDRICreateImageFromBuffer(__DRIcontext *context, |
| + int target, |
| + void *buffer, |
| + unsigned *error, |
| + void *loaderPrivate) |
| +{ |
| + PVRDRIContext *psPVRContext = context->driverPrivate; |
| + __DRIscreen *screen = psPVRContext->psPVRScreen->psDRIScreen; |
| + IMGEGLImage *psEGLImage; |
| + __DRIimage *image; |
| + |
| + switch (target) |
| + { |
| +#if defined(EGL_CL_IMAGE_IMG) |
| + case EGL_CL_IMAGE_IMG: |
| + break; |
| +#endif |
| + default: |
| + errorMessage("%s: Target %d is not supported\n", __func__, target); |
| + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; |
| + return NULL; |
| + } |
| + |
| + image = CommonImageSetup(loaderPrivate); |
| + if (!image) |
| + { |
| + return NULL; |
| + } |
| + |
| + psEGLImage = PVRDRIEGLImageCreate(); |
| + if (!psEGLImage) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + *error = PVRDRIGetImageSource(PVRDRI_API_CL, |
| + psPVRContext->psPVRScreen->psImpl, |
| + psPVRContext->psImpl, |
| + target, |
| + (uintptr_t)buffer, |
| + 0, |
| + psEGLImage); |
| + if (*error != __DRI_IMAGE_ERROR_SUCCESS) |
| + { |
| + PVRDRIEGLImageFree(psEGLImage); |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + PVRDRIEGLImageSetCallbackData(psEGLImage, image); |
| + |
| + /* |
| + * We can't destroy the image after this point, as the |
| + * OCL image now has a reference to it. |
| + */ |
| + image->psShared = CreateImageSharedFromEGLImage(screen, |
| + psEGLImage, |
| + PVRDRI_EGLIMAGE_IMGOCL); |
| + if (!image->psShared) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->psEGLImage = PVRDRIEGLImageDup(image->psShared->psEGLImage); |
| + if (!image->psEGLImage) |
| + { |
| + return NULL; |
| + } |
| + |
| + image->iRefCount++; |
| + |
| + return image; |
| +} |
| + |
| +__DRIimage *PVRDRICreateImageFromDmaBufs(__DRIscreen *screen, |
| + int width, int height, int fourcc, |
| + int *fds, int num_fds, |
| + int *strides, int *offsets, |
| + enum __DRIYUVColorSpace color_space, |
| + enum __DRISampleRange sample_range, |
| + enum __DRIChromaSiting horiz_siting, |
| + enum __DRIChromaSiting vert_siting, |
| + unsigned *error, |
| + void *loaderPrivate) |
| +{ |
| + __DRIimage *image; |
| + |
| + image = CommonImageSetup(loaderPrivate); |
| + if (!image) |
| + { |
| + *error = __DRI_IMAGE_ERROR_BAD_ALLOC; |
| + return NULL; |
| + } |
| + |
| + image->psShared = CreateImageSharedFromDmaBufs(screen, width, height, fourcc, |
| + fds, num_fds, strides, offsets, |
| + color_space, sample_range, |
| + horiz_siting, vert_siting, |
| + error); |
| + if (!image->psShared) |
| + { |
| + PVRDRIDestroyImage(image); |
| + return NULL; |
| + } |
| + |
| + image->psEGLImage = PVRDRIEGLImageCreateFromBuffer(width, height, |
| + strides[0], |
| + image->psShared->psFormat->eIMGPixelFormat, |
| + image->psShared->eColourSpace, |
| + image->psShared->eChromaUInterp, |
| + image->psShared->eChromaVInterp, |
| + image->psShared->psBuffer); |
| + if (!image->psEGLImage) |
| + { |
| + PVRDRIDestroyImage(image); |
| + *error = __DRI_IMAGE_ERROR_BAD_ALLOC; |
| + return NULL; |
| + } |
| + |
| + PVRDRIEGLImageSetCallbackData(image->psEGLImage, image); |
| + |
| + *error = __DRI_IMAGE_ERROR_SUCCESS; |
| + |
| + return image; |
| +} |
| + |
| +void PVRDRIRefImage(__DRIimage *image) |
| +{ |
| + int iRefCount = __sync_fetch_and_add(&image->iRefCount, 1); |
| + |
| + (void)iRefCount; |
| + assert(iRefCount > 0); |
| +} |
| + |
| +void PVRDRIUnrefImage(__DRIimage *image) |
| +{ |
| + PVRDRIDestroyImage(image); |
| +} |
| + |
| +PVRDRIImageType PVRDRIImageGetSharedType(__DRIimage *image) |
| +{ |
| + return image->psShared->eType; |
| +} |
| + |
| +PVRDRIBufferImpl *PVRDRIImageGetSharedBuffer(__DRIimage *pImage) |
| +{ |
| + assert(pImage->psShared->eType != PVRDRI_IMAGE_FROM_EGLIMAGE); |
| + |
| + return pImage->psShared->psBuffer; |
| +} |
| + |
| +IMGEGLImage *PVRDRIImageGetSharedEGLImage(__DRIimage *pImage) |
| +{ |
| + assert(pImage->psShared->eType == PVRDRI_IMAGE_FROM_EGLIMAGE); |
| + return pImage->psShared->psEGLImage; |
| +} |
| + |
| +IMGEGLImage *PVRDRIImageGetEGLImage(__DRIimage *pImage) |
| +{ |
| + return pImage->psEGLImage; |
| +} |
| + |
| +__DRIimage *PVRDRIScreenGetDRIImage(void *hEGLImage) |
| +{ |
| + PVRDRIScreen *psPVRScreen = PVRDRIThreadGetCurrentScreen(); |
| + |
| + if (!psPVRScreen) |
| + { |
| + return NULL; |
| + } |
| + |
| + return psPVRScreen->psDRIScreen->dri2.image->lookupEGLImage( |
| + psPVRScreen->psDRIScreen, |
| + hEGLImage, |
| + psPVRScreen->psDRIScreen->loaderPrivate); |
| +} |
| diff --git a/src/mesa/drivers/dri/pvr/pvrimage.h b/src/mesa/drivers/dri/pvr/pvrimage.h |
| new file mode 100644 |
| index 0000000..2524eca |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrimage.h |
| @@ -0,0 +1,93 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/* |
| + * Copyright (c) Imagination Technologies Ltd. |
| + * |
| + * The contents of this file are subject to the MIT license as set out below. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#if !defined(__PVRIMAGE_H__) |
| +#define __PVRIMAGE_H__ |
| +#include "powervr/dri_support.h" |
| + |
| +__DRIimage *PVRDRICreateImageFromName(__DRIscreen *screen, |
| + int width, int height, int format, |
| + int name, int pitch, |
| + void *loaderPrivate); |
| + |
| +__DRIimage *PVRDRICreateImageFromRenderbuffer(__DRIcontext *context, |
| + int renderbuffer, |
| + void *loaderPrivate); |
| + |
| +void PVRDRIDestroyImage(__DRIimage *image); |
| + |
| +__DRIimage *PVRDRICreateImage(__DRIscreen *screen, |
| + int width, int height, int format, |
| + unsigned int use, |
| + void *loaderPrivate); |
| + |
| +GLboolean PVRDRIQueryImage(__DRIimage *image, int attrib, int *value); |
| + |
| +__DRIimage *PVRDRIDupImage(__DRIimage *image, void *loaderPrivate); |
| + |
| +GLboolean PVRDRIValidateUsage(__DRIimage *image, unsigned int use); |
| + |
| +__DRIimage *PVRDRICreateImageFromNames(__DRIscreen *screen, |
| + int width, int height, int fourcc, |
| + int *names, int num_names, |
| + int *strides, int *offsets, |
| + void *loaderPrivate); |
| + |
| +__DRIimage *PVRDRIFromPlanar(__DRIimage *image, int plane, |
| + void *loaderPrivate); |
| + |
| +__DRIimage *PVRDRICreateImageFromTexture(__DRIcontext *context, |
| + int glTarget, |
| + unsigned texture, |
| + int depth, |
| + int level, |
| + unsigned *error, |
| + void *loaderPrivate); |
| + |
| +__DRIimage *PVRDRICreateImageFromFds(__DRIscreen *screen, |
| + int width, int height, int fourcc, |
| + int *fds, int num_fds, |
| + int *strides, int *offsets, |
| + void *loaderPrivate); |
| + |
| +__DRIimage *PVRDRICreateImageFromBuffer(__DRIcontext *context, |
| + int target, |
| + void *buffer, |
| + unsigned *error, |
| + void *loaderPrivate); |
| + |
| +__DRIimage *PVRDRICreateImageFromDmaBufs(__DRIscreen *screen, |
| + int width, int height, int fourcc, |
| + int *fds, int num_fds, |
| + int *strides, int *offsets, |
| + enum __DRIYUVColorSpace color_space, |
| + enum __DRISampleRange sample_range, |
| + enum __DRIChromaSiting horiz_siting, |
| + enum __DRIChromaSiting vert_siting, |
| + unsigned *error, |
| + void *loaderPrivate); |
| + |
| +#endif /* !defined(__PVRIMAGE_H__) */ |
| diff --git a/src/mesa/drivers/dri/pvr/pvrmesa.h b/src/mesa/drivers/dri/pvr/pvrmesa.h |
| new file mode 100644 |
| index 0000000..6e0fd8d |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrmesa.h |
| @@ -0,0 +1,41 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/* |
| + * Copyright (c) Imagination Technologies Ltd. |
| + * |
| + * The contents of this file are subject to the MIT license as set out below. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#if !defined(__PVRMESA_H__) |
| +#define __PVRMESA_H__ |
| + |
| +#include "pvrdri.h" |
| + |
| +void pvrdri_free_dispatch_tables(PVRDRIScreen *psPVRScreen); |
| + |
| +bool pvrdri_create_dispatch_table(PVRDRIScreen *psPVRScreen, |
| + PVRDRIAPIType eAPI); |
| + |
| +void pvrdri_set_null_dispatch_table(void); |
| + |
| +void pvrdri_set_dispatch_table(PVRDRIContext *psPVRContext); |
| + |
| +#endif /* !defined(__PVRMESA_H__) */ |
| diff --git a/src/mesa/drivers/dri/pvr/pvrqueue.h b/src/mesa/drivers/dri/pvr/pvrqueue.h |
| new file mode 100644 |
| index 0000000..3fdc0a8 |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrqueue.h |
| @@ -0,0 +1,74 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/*************************************************************************/ /*! |
| +@File pvrqueue.h |
| +@Title Queue related definitions |
| +@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved |
| +@License MIT |
| + |
| +The contents of this file are subject to the MIT license as set out below. |
| + |
| +Permission is hereby granted, free of charge, to any person obtaining a copy |
| +of this software and associated documentation files (the "Software"), to deal |
| +in the Software without restriction, including without limitation the rights |
| +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| +copies of the Software, and to permit persons to whom the Software is |
| +furnished to do so, subject to the following conditions: |
| + |
| +The above copyright notice and this permission notice shall be included in |
| +all copies or substantial portions of the Software. |
| + |
| +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| +THE SOFTWARE. |
| +*/ /**************************************************************************/ |
| + |
| +#if !defined(__PVRQUEUE_H__) |
| +#define __PVRQUEUE_H__ |
| +#include <assert.h> |
| +#include <search.h> |
| +#include <stddef.h> |
| + |
| +#define PVRQ_CONTAINER_OF(p, t, f) ((t *)((char *)(p) - offsetof(t, f))) |
| + |
| +typedef struct _PVRQElem |
| +{ |
| + struct _PVRQElem *pvForw; |
| + struct _PVRQElem *pvBack; |
| +} PVRQElem; |
| + |
| +typedef PVRQElem PVRQHead; |
| + |
| +#define DECLARE_PVRQ_HEAD(h) PVRQHead h = {&h, &h} |
| + |
| +static inline void INITIALISE_PVRQ_HEAD(PVRQHead *ph) |
| +{ |
| + ph->pvForw = ph->pvBack = ph; |
| + insque(ph, ph); |
| +} |
| + |
| +static inline int PVRQIsEmpty(PVRQHead *ph) |
| +{ |
| + return ph->pvForw == ph && ph->pvBack == ph; |
| +} |
| + |
| +static inline void PVRQQueue(PVRQHead *ph, PVRQElem *pe) |
| +{ |
| + assert(pe->pvForw == NULL && pe->pvBack == NULL); |
| + |
| + insque(pe, ph->pvBack); |
| +} |
| + |
| +static inline void PVRQDequeue(PVRQElem *pe) |
| +{ |
| + remque(pe); |
| + |
| + pe->pvForw = NULL; |
| + pe->pvBack = NULL; |
| +} |
| + |
| +#endif /* defined(__PVRQUEUE_H__) */ |
| diff --git a/src/mesa/drivers/dri/pvr/pvrutil.c b/src/mesa/drivers/dri/pvr/pvrutil.c |
| new file mode 100644 |
| index 0000000..53d4fd4 |
| --- /dev/null |
| +++ b/src/mesa/drivers/dri/pvr/pvrutil.c |
| @@ -0,0 +1,589 @@ |
| +/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
| +/* vi: set ts=8 sw=8 sts=8: */ |
| +/* |
| + * Copyright (c) Imagination Technologies Ltd. |
| + * |
| + * The contents of this file are subject to the MIT license as set out below. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| + * of this software and associated documentation files (the "Software"), to deal |
| + * in the Software without restriction, including without limitation the rights |
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| + * copies of the Software, and to permit persons to whom the Software is |
| + * furnished to do so, subject to the following conditions: |
| + * |
| + * The above copyright notice and this permission notice shall be included in |
| + * all copies or substantial portions of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| + * THE SOFTWARE. |
| + */ |
| + |
| +#include <assert.h> |
| +#include <stdarg.h> |
| +#include <stdio.h> |
| + |
| +#include "utils.h" |
| +#include "GL/gl.h" |
| + |
| +#include "pvrdri.h" |
| + |
| +#define MESSAGE_LENGTH_MAX 1024 |
| + |
| +/* |
| + * define before including android/log.h and dlog.h as this is used by these |
| + * headers |
| + */ |
| +#define LOG_TAG "PVR-MESA" |
| + |
| +#if defined(HAVE_ANDROID_PLATFORM) |
| +#include <android/log.h> |
| +#define err_printf(f, args...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, f, ##args)) |
| +#define dbg_printf(f, args...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, f, ##args)) |
| +#elif defined(HAVE_TIZEN_PLATFORM) |
| +#include <dlog.h> |
| +#define err_printf(f, args...) LOGE(f, ##args) |
| +#define dbg_printf(f, args...) LOGD(f, ##args) |
| +#else |
| +#define err_printf(f, args...) fprintf(stderr, f, ##args) |
| +#define dbg_printf(f, args...) fprintf(stderr, "LibGL: " f "\n", ##args) |
| +#endif /* HAVE_ANDROID_PLATFORM */ |
| + |
| +#define PVRDRIMesaFormatEntry(f) {f, PVRDRI_ ## f } |
| + |
| +static const struct |
| +{ |
| + mesa_format eMesa; |
| + unsigned uPVRDRI; |
| +} g_asMesaFormats[] = { |
| + PVRDRIMesaFormatEntry(MESA_FORMAT_B8G8R8A8_UNORM), |
| + PVRDRIMesaFormatEntry(MESA_FORMAT_B8G8R8X8_UNORM), |
| +#ifdef HAVE_ANDROID_PLATFORM |
| + PVRDRIMesaFormatEntry(MESA_FORMAT_R8G8B8A8_UNORM), |
| + PVRDRIMesaFormatEntry(MESA_FORMAT_R8G8B8X8_UNORM), |
| +#endif |
| + PVRDRIMesaFormatEntry(MESA_FORMAT_B5G6R5_UNORM), |
| +}; |
| + |
| +/* See pvrdri.h for documentation on PVRDRIImageFormat */ |
| +static const PVRDRIImageFormat g_asFormats[] = |
| +{ |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_B8G8R8A8_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_ARGB8888, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_ARGB8888, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RGBA, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_R8G8B8A8_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_ABGR8888, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_ABGR8888, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RGBA, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_B8G8R8X8_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_XRGB8888, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_XRGB8888, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RGB, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_R8G8B8X8_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_XBGR8888, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_XBGR8888, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RGB, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_B5G6R5_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_RGB565, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_RGB565, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RGB, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_R8G8_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_GR88, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_GR88, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RG, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_R8_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_R8, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_R8, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_R, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_L8A8_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_GR88, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_GR88, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RG, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_L8_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_R8, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_R8, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_R, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_D32_FLOAT, |
| + .iDRIFourCC = 0, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_NONE, |
| + .iDRIComponents = 0, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_S8_UINT, |
| + .iDRIFourCC = 0, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_NONE, |
| + .iDRIComponents = 0, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| +#if defined(__DRI_IMAGE_FORMAT_ARGB4444) |
| + /* We patch this format into Mesa */ |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_B4G4R4A4_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_ARGB4444, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_ARGB4444, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RGBA, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| +#endif |
| +#if defined(__DRI_IMAGE_FORMAT_ARGB1555) |
| + /* We patch this format into Mesa */ |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_B5G5R5A1_UNORM, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_ARGB1555, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_ARGB1555, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_RGBA, |
| + .uiNumPlanes = 1, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + }, |
| +#endif |
| +#if defined(__DRI_IMAGE_FOURCC_MT21) |
| + /* We patch this format into Mesa */ |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_YVU8_420_2PLANE_PACK8_P, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_MT21, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_NONE, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_Y_UV, |
| + .uiNumPlanes = 2, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + .sPlanes[1] = |
| + { |
| + .uiWidthShift = 1, |
| + .uiHeightShift = 1 |
| + }, |
| + }, |
| +#endif |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_YUV420_2PLANE, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_NV12, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_NONE, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_Y_UV, |
| + .uiNumPlanes = 2, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + .sPlanes[1] = |
| + { |
| + .uiWidthShift = 1, |
| + .uiHeightShift = 1 |
| + }, |
| + }, |
| +#if defined(__DRI_IMAGE_FOURCC_NV21) |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_YVU420_2PLANE, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_NV21, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_NONE, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_Y_UV, |
| + .uiNumPlanes = 2, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + .sPlanes[1] = |
| + { |
| + .uiWidthShift = 1, |
| + .uiHeightShift = 1 |
| + }, |
| + }, |
| +#endif |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_YUV420_3PLANE, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_YUV420, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_NONE, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_Y_U_V, |
| + .uiNumPlanes = 3, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + .sPlanes[1] = |
| + { |
| + .uiWidthShift = 1, |
| + .uiHeightShift = 1 |
| + }, |
| + .sPlanes[2] = |
| + { |
| + .uiWidthShift = 1, |
| + .uiHeightShift = 1 |
| + }, |
| + }, |
| + { |
| + .eIMGPixelFormat = IMG_PIXFMT_YVU420_3PLANE, |
| + .iDRIFourCC = __DRI_IMAGE_FOURCC_YVU420, |
| + .iDRIFormat = __DRI_IMAGE_FORMAT_NONE, |
| + .iDRIComponents = __DRI_IMAGE_COMPONENTS_Y_U_V, |
| + .uiNumPlanes = 3, |
| + .sPlanes[0] = |
| + { |
| + .uiWidthShift = 0, |
| + .uiHeightShift = 0 |
| + }, |
| + .sPlanes[1] = |
| + { |
| + .uiWidthShift = 1, |
| + .uiHeightShift = 1 |
| + }, |
| + .sPlanes[2] = |
| + { |
| + .uiWidthShift = 1, |
| + .uiHeightShift = 1 |
| + }, |
| + }, |
| +}; |
| + |
| +/* Standard error message */ |
| +void __attribute__((format(printf, 1, 2))) errorMessage(const char *f, ...) |
| +{ |
| + char message[MESSAGE_LENGTH_MAX]; |
| + va_list args; |
| + |
| + va_start(args, f); |
| + vsnprintf(message, sizeof message, f, args); |
| + va_end(args); |
| + |
| + err_printf("%s", message); |
| +} |
| + |
| +void __attribute__((format(printf, 1, 2))) __driUtilMessage(const char *f, ...) |
| +{ |
| +#if defined(HAVE_ANDROID_PLATFORM) || defined(HAVE_TIZEN_PLATFORM) |
| + char *ev = getenv("LIBGL_DEBUG"); |
| + |
| + if (ev != NULL && (strcmp(ev, "verbose") == 0)) |
| +#endif |
| + { |
| + char message[MESSAGE_LENGTH_MAX]; |
| + va_list args; |
| + |
| + va_start(args, f); |
| + vsnprintf(message, sizeof message, f, args); |
| + va_end(args); |
| + |
| + dbg_printf("%s", message); |
| + } |
| +} |
| + |
| +const __DRIconfig **PVRDRICreateConfigs(void) |
| +{ |
| + static const GLenum asBackBufferModes[] = { GLX_NONE, GLX_SWAP_UNDEFINED_OML }; |
| + const uint8_t *puDepthBits = PVRDRIDepthBitsArray(); |
| + const uint8_t *puStencilBits = PVRDRIStencilBitsArray(); |
| + const uint8_t *puMSAASamples = PVRDRIMSAABitsArray(); |
| + const unsigned uNumBackBufferModes = ARRAY_SIZE(asBackBufferModes); |
| + const unsigned uNumDepthStencilBits = PVRDRIDepthStencilBitArraySize(); |
| + const unsigned uNumMSAASamples = PVRDRIMSAABitArraySize(); |
| + __DRIconfig **ppsConfigs = NULL; |
| + __DRIconfig **ppsNewConfigs; |
| + unsigned i; |
| + |
| + for (i = 0; i < ARRAY_SIZE(g_asMesaFormats); i++) |
| + { |
| + if (!PVRDRIMesaFormatSupported(g_asMesaFormats[i].uPVRDRI)) |
| + continue; |
| + |
| + ppsNewConfigs = driCreateConfigs(g_asMesaFormats[i].eMesa, |
| + puDepthBits, |
| + puStencilBits, |
| + uNumDepthStencilBits, |
| + asBackBufferModes, |
| + uNumBackBufferModes, |
| + puMSAASamples, |
| + uNumMSAASamples, |
| + GL_FALSE, |
| + GL_FALSE); |
| + |
| + ppsConfigs = driConcatConfigs(ppsConfigs, ppsNewConfigs); |
| + } |
| + |
| + if (ppsConfigs) |
| + { |
| + for (i = 0; ppsConfigs[i]; i++) |
| + { |
| + ppsConfigs[i]->modes.maxPbufferWidth = |
| + PVRDRIMaxPBufferWidth(); |
| + ppsConfigs[i]->modes.maxPbufferHeight = |
| + PVRDRIMaxPBufferHeight(); |
| + |
| + ppsConfigs[i]->modes.maxPbufferPixels = |
| + PVRDRIMaxPBufferWidth() * |
| + PVRDRIMaxPBufferHeight(); |
| + } |
| + } |
| + |
| + return (const __DRIconfig **)ppsConfigs; |
| +} |
| + |
| +const PVRDRIImageFormat *PVRDRIFormatToImageFormat(int iDRIFormat) |
| +{ |
| + unsigned i; |
| + |
| + assert(iDRIFormat != __DRI_IMAGE_FORMAT_NONE); |
| + |
| + for (i = 0; i < ARRAY_SIZE(g_asFormats); i++) |
| + { |
| + if (g_asFormats[i].iDRIFormat == iDRIFormat) |
| + { |
| + return &g_asFormats[i]; |
| + } |
| + } |
| + |
| + return NULL; |
| +} |
| + |
| +const PVRDRIImageFormat *PVRDRIFourCCToImageFormat(int iDRIFourCC) |
| +{ |
| + unsigned i; |
| + |
| + assert(iDRIFourCC); |
| + |
| + for (i = 0; i < ARRAY_SIZE(g_asFormats); i++) |
| + { |
| + if (g_asFormats[i].iDRIFourCC == iDRIFourCC) |
| + { |
| + return &g_asFormats[i]; |
| + } |
| + } |
| + |
| + return NULL; |
| +} |
| + |
| +const PVRDRIImageFormat *PVRDRIIMGPixelFormatToImageFormat(IMG_PIXFMT eIMGPixelFormat) |
| +{ |
| + unsigned i; |
| + |
| + assert(eIMGPixelFormat != IMG_PIXFMT_UNKNOWN); |
| + |
| + for (i = 0; i < ARRAY_SIZE(g_asFormats); i++) |
| + { |
| + if (g_asFormats[i].eIMGPixelFormat == eIMGPixelFormat) |
| + { |
| + return &g_asFormats[i]; |
| + } |
| + } |
| + |
| + return NULL; |
| +} |
| + |
| +/* |
| + * The EGL_EXT_image_dma_buf_import says that if a hint is unspecified then |
| + * the implementation may guess based on the pixel format or may fallback |
| + * to some default value. Furthermore, if a hint is unsupported then the |
| + * implementation may use whichever settings it wants to achieve the closest |
| + * match. |
| + */ |
| +IMG_YUV_COLORSPACE PVRDRIToIMGColourSpace(const PVRDRIImageFormat *psFormat, |
| + enum __DRIYUVColorSpace eDRIColourSpace, |
| + enum __DRISampleRange eDRISampleRange) |
| +{ |
| + switch (psFormat->iDRIComponents) |
| + { |
| + case __DRI_IMAGE_COMPONENTS_R: |
| + case __DRI_IMAGE_COMPONENTS_RG: |
| + case __DRI_IMAGE_COMPONENTS_RGB: |
| + case __DRI_IMAGE_COMPONENTS_RGBA: |
| + return IMG_COLORSPACE_UNDEFINED; |
| + case __DRI_IMAGE_COMPONENTS_Y_U_V: |
| + case __DRI_IMAGE_COMPONENTS_Y_UV: |
| + case __DRI_IMAGE_COMPONENTS_Y_XUXV: |
| + break; |
| + default: |
| + errorMessage("Unrecognised DRI components (components = 0x%X)\n", |
| + psFormat->iDRIComponents); |
| + assert(0); |
| + return IMG_COLORSPACE_UNDEFINED; |
| + } |
| + |
| + switch (eDRIColourSpace) |
| + { |
| + case __DRI_YUV_COLOR_SPACE_UNDEFINED: |
| + case __DRI_YUV_COLOR_SPACE_ITU_REC601: |
| + switch (eDRISampleRange) |
| + { |
| + case __DRI_YUV_RANGE_UNDEFINED: |
| + case __DRI_YUV_NARROW_RANGE: |
| + return IMG_COLORSPACE_BT601_CONFORMANT_RANGE; |
| + case __DRI_YUV_FULL_RANGE: |
| + return IMG_COLORSPACE_BT601_FULL_RANGE; |
| + default: |
| + errorMessage("Unrecognised DRI sample range (sample range = 0x%X)\n", |
| + eDRISampleRange); |
| + assert(0); |
| + return IMG_COLORSPACE_UNDEFINED; |
| + } |
| + case __DRI_YUV_COLOR_SPACE_ITU_REC709: |
| + switch (eDRISampleRange) |
| + { |
| + case __DRI_YUV_RANGE_UNDEFINED: |
| + case __DRI_YUV_NARROW_RANGE: |
| + return IMG_COLORSPACE_BT709_CONFORMANT_RANGE; |
| + case __DRI_YUV_FULL_RANGE: |
| + return IMG_COLORSPACE_BT709_FULL_RANGE; |
| + default: |
| + errorMessage("Unrecognised DRI sample range (sample range = 0x%X)\n", |
| + eDRISampleRange); |
| + assert(0); |
| + return IMG_COLORSPACE_UNDEFINED; |
| + } |
| + case __DRI_YUV_COLOR_SPACE_ITU_REC2020: |
| + switch (eDRISampleRange) |
| + { |
| + case __DRI_YUV_RANGE_UNDEFINED: |
| + case __DRI_YUV_NARROW_RANGE: |
| + return IMG_COLORSPACE_BT2020_CONFORMANT_RANGE; |
| + case __DRI_YUV_FULL_RANGE: |
| + return IMG_COLORSPACE_BT2020_FULL_RANGE; |
| + default: |
| + errorMessage("Unrecognised DRI sample range (sample range = 0x%X)\n", |
| + eDRISampleRange); |
| + assert(0); |
| + return IMG_COLORSPACE_UNDEFINED; |
| + } |
| + default: |
| + errorMessage("Unrecognised DRI colour space (colour space = 0x%X)\n", |
| + eDRIColourSpace); |
| + assert(0); |
| + return IMG_COLORSPACE_UNDEFINED; |
| + } |
| +} |
| + |
| +IMG_YUV_CHROMA_INTERP PVRDRIChromaSittingToIMGInterp(const PVRDRIImageFormat *psFormat, |
| + enum __DRIChromaSiting eChromaSitting) |
| +{ |
| + switch (psFormat->iDRIComponents) |
| + { |
| + case __DRI_IMAGE_COMPONENTS_R: |
| + case __DRI_IMAGE_COMPONENTS_RG: |
| + case __DRI_IMAGE_COMPONENTS_RGB: |
| + case __DRI_IMAGE_COMPONENTS_RGBA: |
| + return IMG_CHROMA_INTERP_UNDEFINED; |
| + case __DRI_IMAGE_COMPONENTS_Y_U_V: |
| + case __DRI_IMAGE_COMPONENTS_Y_UV: |
| + case __DRI_IMAGE_COMPONENTS_Y_XUXV: |
| + break; |
| + default: |
| + errorMessage("Unrecognised DRI components (components = 0x%X)\n", |
| + psFormat->iDRIComponents); |
| + assert(0); |
| + return IMG_CHROMA_INTERP_UNDEFINED; |
| + } |
| + |
| + switch (eChromaSitting) |
| + { |
| + case __DRI_YUV_CHROMA_SITING_UNDEFINED: |
| + case __DRI_YUV_CHROMA_SITING_0: |
| + return IMG_CHROMA_INTERP_ZERO; |
| + case __DRI_YUV_CHROMA_SITING_0_5: |
| + return IMG_CHROMA_INTERP_HALF; |
| + default: |
| + errorMessage("Unrecognised DRI chroma sitting (chroma sitting = 0x%X)\n", |
| + eChromaSitting); |
| + assert(0); |
| + return IMG_CHROMA_INTERP_UNDEFINED; |
| + } |
| +} |
| -- |
| 2.7.4 |
| |