Compare commits
20 Commits
mesa-18.3.
...
chadv/wip/
Author | SHA1 | Date | |
---|---|---|---|
|
8cb2b5c37a | ||
|
6158e78240 | ||
|
c689a23c77 | ||
|
0cbe8ad97d | ||
|
f57e2bf44e | ||
|
3274c56585 | ||
|
0a957c2822 | ||
|
6ac5d83a6c | ||
|
53ba2797ee | ||
|
58cbc48eac | ||
|
c884f74c5f | ||
|
ca6dc3b7f4 | ||
|
f7f64ad0ac | ||
|
97636c85f9 | ||
|
f408dc0e46 | ||
|
15656ccb9e | ||
|
09a9aafa81 | ||
|
d346f5b8bd | ||
|
ab8ac2c3e9 | ||
|
d069832666 |
10
PRESUBMIT.cfg
Normal file
10
PRESUBMIT.cfg
Normal file
@@ -0,0 +1,10 @@
|
||||
# This sample config file disables all of the ChromiumOS source style checks.
|
||||
# Comment out the disable-flags for any checks you want to leave enabled.
|
||||
|
||||
[Hook Overrides]
|
||||
stray_whitespace_check: false
|
||||
long_line_check: false
|
||||
cros_license_check: false
|
||||
tab_check: false
|
||||
bug_field_check: false
|
||||
test_field_check: false
|
@@ -1831,6 +1831,9 @@ for plat in $platforms; do
|
||||
|
||||
android)
|
||||
PKG_CHECK_MODULES([ANDROID], [cutils hardware sync])
|
||||
if test -n "$with_gallium_drivers"; then
|
||||
PKG_CHECK_MODULES([BACKTRACE], [backtrace])
|
||||
fi
|
||||
DEFINES="$DEFINES -DHAVE_ANDROID_PLATFORM"
|
||||
;;
|
||||
|
||||
|
@@ -48,6 +48,7 @@ typedef unsigned int drm_drawable_t;
|
||||
typedef struct drm_clip_rect drm_clip_rect_t;
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
@@ -746,7 +747,8 @@ struct __DRIuseInvalidateExtensionRec {
|
||||
#define __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS 46
|
||||
#define __DRI_ATTRIB_YINVERTED 47
|
||||
#define __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE 48
|
||||
#define __DRI_ATTRIB_MAX (__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE + 1)
|
||||
#define __DRI_ATTRIB_MUTABLE_RENDER_BUFFER 49 /* EGL_MUTABLE_RENDER_BUFFER_BIT_KHR */
|
||||
#define __DRI_ATTRIB_MAX 50
|
||||
|
||||
/* __DRI_ATTRIB_RENDER_TYPE */
|
||||
#define __DRI_ATTRIB_RGBA_BIT 0x01
|
||||
@@ -1888,9 +1890,57 @@ struct __DRI2rendererQueryExtensionRec {
|
||||
* Image Loader extension. Drivers use this to allocate color buffers
|
||||
*/
|
||||
|
||||
/**
|
||||
* See __DRIimageLoaderExtensionRec::getBuffers::buffer_mask.
|
||||
*/
|
||||
enum __DRIimageBufferMask {
|
||||
__DRI_IMAGE_BUFFER_BACK = (1 << 0),
|
||||
__DRI_IMAGE_BUFFER_FRONT = (1 << 1)
|
||||
__DRI_IMAGE_BUFFER_FRONT = (1 << 1),
|
||||
|
||||
/**
|
||||
* A buffer shared between application and compositor. The buffer may be
|
||||
* simultaneously accessed by each.
|
||||
*
|
||||
* A shared buffer is equivalent to an EGLSurface whose EGLConfig contains
|
||||
* EGL_MUTABLE_RENDER_BUFFER_BIT_KHR and whose active EGL_RENDER_BUFFER (as
|
||||
* opposed to any pending, requested change to EGL_RENDER_BUFFER) is
|
||||
* EGL_SINGLE_BUFFER.
|
||||
*
|
||||
* If buffer_mask contains __DRI_IMAGE_BUFFER_SHARED, then must contains no
|
||||
* other bits. As a corollary, a __DRIdrawable that has a "shared" buffer
|
||||
* has no front nor back buffer.
|
||||
*
|
||||
* The loader returns __DRI_IMAGE_BUFFER_SHARED in buffer_mask if and only
|
||||
* if:
|
||||
* - The loader supports __DRI_MUTABLE_RENDER_BUFFER_LOADER.
|
||||
* - The driver supports __DRI_MUTABLE_RENDER_BUFFER_DRIVER.
|
||||
* - The EGLConfig of the drawable EGLSurface contains
|
||||
* EGL_MUTABLE_RENDER_BUFFER_BIT_KHR.
|
||||
* - The EGLContext's EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER.
|
||||
* Equivalently, the EGLSurface's active EGL_RENDER_BUFFER (as
|
||||
* opposed to any pending, requested change to EGL_RENDER_BUFFER) is
|
||||
* EGL_SINGLE_BUFFER. (See the EGL 1.5 and
|
||||
* EGL_KHR_mutable_render_buffer spec for details about "pending" vs
|
||||
* "active" EGL_RENDER_BUFFER state).
|
||||
*
|
||||
* A shared buffer is similar to a front buffer in that all rendering to the
|
||||
* buffer should appear promptly on the screen. It is different from
|
||||
* a front buffer in that its behavior is independent from the
|
||||
* GL_DRAW_BUFFER state. Specifically, if GL_DRAW_FRAMEBUFFER is 0 and the
|
||||
* __DRIdrawable's buffer_mask is __DRI_IMAGE_BUFFER_SHARED, then all
|
||||
* rendering should appear promptly on the screen if GL_DRAW_BUFFER is not
|
||||
* GL_NONE.
|
||||
*
|
||||
* The difference between a shared buffer and a front buffer is motivated
|
||||
* by the constraints of Android and OpenGL ES. OpenGL ES does not support
|
||||
* front-buffer rendering. Android's SurfaceFlinger protocol provides the
|
||||
* EGL driver only a back buffer and no front buffer. The shared buffer
|
||||
* mode introduced by EGL_KHR_mutable_render_buffer is a backdoor though
|
||||
* EGL that allows Android OpenGL ES applications to render to what is
|
||||
* effectively the front buffer, a backdoor that required no change to the
|
||||
* OpenGL ES API and little change to the SurfaceFlinger API.
|
||||
*/
|
||||
__DRI_IMAGE_BUFFER_SHARED = (1 << 2),
|
||||
};
|
||||
|
||||
struct __DRIimageList {
|
||||
@@ -1915,7 +1965,8 @@ struct __DRIimageLoaderExtensionRec {
|
||||
* \param stamp Address of variable to be updated when
|
||||
* getBuffers must be called again
|
||||
* \param loaderPrivate The loaderPrivate for driDrawable
|
||||
* \param buffer_mask Set of buffers to allocate
|
||||
* \param buffer_mask Set of buffers to allocate. A bitmask of
|
||||
* __DRIimageBufferMask.
|
||||
* \param buffers Returned buffers
|
||||
*/
|
||||
int (*getBuffers)(__DRIdrawable *driDrawable,
|
||||
@@ -2029,4 +2080,85 @@ struct __DRIbackgroundCallableExtensionRec {
|
||||
GLboolean (*isThreadSafe)(void *loaderPrivate);
|
||||
};
|
||||
|
||||
/**
|
||||
* The driver portion of EGL_KHR_mutable_render_buffer.
|
||||
*
|
||||
* If the driver creates a __DRIconfig with
|
||||
* __DRI_ATTRIB_MUTABLE_RENDER_BUFFER, then it must support this extension.
|
||||
*
|
||||
* To support this extension:
|
||||
*
|
||||
* - The driver should create at least one __DRIconfig with
|
||||
* __DRI_ATTRIB_MUTABLE_RENDER_BUFFER. This is strongly recommended but
|
||||
* not required.
|
||||
*
|
||||
* - The driver must be able to handle __DRI_IMAGE_BUFFER_SHARED if
|
||||
* returned by __DRIimageLoaderExtension:getBuffers().
|
||||
*
|
||||
* - When rendering to __DRI_IMAGE_BUFFER_SHARED, it must call
|
||||
* __DRImutableRenderBufferLoaderExtension::displaySharedBuffer() in
|
||||
* response to glFlush and glFinish. (This requirement is not documented
|
||||
* in EGL_KHR_mutable_render_buffer, but is a de-facto requirement in the
|
||||
* Android ecosystem. Android applications expect that glFlush will
|
||||
* immediately display the buffer when in shared buffer mode, and Android
|
||||
* drivers comply with this expectation). It :may: call
|
||||
* displaySharedBuffer() more often than required.
|
||||
*
|
||||
* - When rendering to __DRI_IMAGE_BUFFER_SHARED, it must ensure that the
|
||||
* buffer is always in a format compatible for display because the
|
||||
* display engine (usually SurfaceFlinger or hwcomposer) may display the
|
||||
* image at any time, even concurrently with 3D rendering. For example,
|
||||
* display hardware and the GL hardware may be able to access the buffer
|
||||
* simultaneously. In particular, if the buffer is compressed then take
|
||||
* care that SurfaceFlinger and hwcomposer can consume the compression
|
||||
* format.
|
||||
*
|
||||
* \see __DRI_IMAGE_BUFFER_SHARED
|
||||
* \see __DRI_ATTRIB_MUTABLE_RENDER_BUFFER
|
||||
* \see __DRI_MUTABLE_RENDER_BUFFER_LOADER
|
||||
*/
|
||||
#define __DRI_MUTABLE_RENDER_BUFFER_DRIVER "DRI_MutableRenderBufferDriver"
|
||||
#define __DRI_MUTABLE_RENDER_BUFFER_DRIVER_VERSION 1
|
||||
|
||||
typedef struct __DRImutableRenderBufferDriverExtensionRec __DRImutableRenderBufferDriverExtension;
|
||||
struct __DRImutableRenderBufferDriverExtensionRec {
|
||||
__DRIextension base;
|
||||
};
|
||||
|
||||
/**
|
||||
* The loader portion of EGL_KHR_mutable_render_buffer.
|
||||
*
|
||||
* Requires loader extension DRI_IMAGE_LOADER, through which the loader sends
|
||||
* __DRI_IMAGE_BUFFER_SHARED to the driver.
|
||||
*
|
||||
* \see __DRI_MUTABLE_RENDER_BUFFER_DRIVER
|
||||
*/
|
||||
#define __DRI_MUTABLE_RENDER_BUFFER_LOADER "DRI_MutableRenderBufferLoader"
|
||||
#define __DRI_MUTABLE_RENDER_BUFFER_LOADER_VERSION 1
|
||||
|
||||
typedef struct __DRImutableRenderBufferLoaderExtensionRec __DRImutableRenderBufferLoaderExtension;
|
||||
struct __DRImutableRenderBufferLoaderExtensionRec {
|
||||
__DRIextension base;
|
||||
|
||||
/**
|
||||
* Inform the display engine (that is, SurfaceFlinger and/or hwcomposer)
|
||||
* that the __DRIdrawable has new content.
|
||||
*
|
||||
* The display engine may ignore this call, for example, if it continually
|
||||
* refreshes and displays the buffer on every frame, as in
|
||||
* EGL_ANDROID_front_buffer_auto_refresh. On the other extreme, the display
|
||||
* engine may refresh and display the buffer only in frames in which the
|
||||
* driver calls this.
|
||||
*
|
||||
* If the fence_fd is not -1, then the display engine will display the
|
||||
* buffer only after the fence signals.
|
||||
*
|
||||
* The drawable's current __DRIimageBufferMask, as returned by
|
||||
* __DRIimageLoaderExtension::getBuffers(), must be
|
||||
* __DRI_IMAGE_BUFFER_SHARED.
|
||||
*/
|
||||
void (*displaySharedBuffer)(__DRIdrawable *drawable, int fence_fd,
|
||||
void *loaderPrivate);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -224,10 +224,12 @@ expanded_line:
|
||||
glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro);
|
||||
_glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2.value);
|
||||
}
|
||||
| LINE_EXPANDED integer_constant NEWLINE {
|
||||
| LINE_EXPANDED expression NEWLINE {
|
||||
if (parser->is_gles && $2.undefined_macro)
|
||||
glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro);
|
||||
parser->has_new_line_number = 1;
|
||||
parser->new_line_number = $2;
|
||||
_mesa_string_buffer_printf(parser->output, "#line %" PRIiMAX "\n", $2);
|
||||
parser->new_line_number = $2.value;
|
||||
_mesa_string_buffer_printf(parser->output, "#line %" PRIiMAX "\n", $2.value);
|
||||
}
|
||||
| LINE_EXPANDED integer_constant integer_constant NEWLINE {
|
||||
parser->has_new_line_number = 1;
|
||||
@@ -238,6 +240,19 @@ expanded_line:
|
||||
"#line %" PRIiMAX " %" PRIiMAX "\n",
|
||||
$2, $3);
|
||||
}
|
||||
| LINE_EXPANDED '(' expression ')' '(' expression ')' NEWLINE {
|
||||
if (parser->is_gles && $3.undefined_macro)
|
||||
glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $3.undefined_macro);
|
||||
if (parser->is_gles && $6.undefined_macro)
|
||||
glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $6.undefined_macro);
|
||||
parser->has_new_line_number = 1;
|
||||
parser->new_line_number = $3.value;
|
||||
parser->has_new_source_number = 1;
|
||||
parser->new_source_number = $6.value;
|
||||
_mesa_string_buffer_printf(parser->output,
|
||||
"#line %" PRIiMAX " %" PRIiMAX "\n",
|
||||
$3.value, $6.value);
|
||||
}
|
||||
;
|
||||
|
||||
define:
|
||||
|
@@ -671,6 +671,9 @@ private:
|
||||
this->record_next_sampler))
|
||||
return;
|
||||
|
||||
/* Avoid overflowing the sampler array. (crbug.com/141901) */
|
||||
this->next_sampler = MIN2(this->next_sampler, MAX_SAMPLERS);
|
||||
|
||||
for (unsigned i = uniform->opaque[shader_type].index;
|
||||
i < MIN2(this->next_sampler, MAX_SAMPLERS);
|
||||
i++) {
|
||||
|
@@ -41,6 +41,7 @@ LOCAL_SRC_FILES := \
|
||||
LOCAL_CFLAGS := \
|
||||
-D_EGL_NATIVE_PLATFORM=_EGL_PLATFORM_ANDROID \
|
||||
-D_EGL_BUILT_IN_DRIVER_DRI2 \
|
||||
-DHAS_GRALLOC_DRM_HEADERS \
|
||||
-DHAVE_ANDROID_PLATFORM
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
|
@@ -108,7 +108,9 @@ endif
|
||||
if HAVE_PLATFORM_ANDROID
|
||||
AM_CFLAGS += $(ANDROID_CFLAGS)
|
||||
libEGL_common_la_LIBADD += $(ANDROID_LIBS)
|
||||
dri2_backend_FILES += drivers/dri2/platform_android.c
|
||||
dri2_backend_FILES += \
|
||||
drivers/dri2/platform_android.c \
|
||||
drivers/dri2/egl_dri2_drm_gralloc.h
|
||||
endif
|
||||
|
||||
AM_CFLAGS += \
|
||||
|
@@ -300,7 +300,10 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
|
||||
_eglSetConfigKey(&base, EGL_MAX_PBUFFER_HEIGHT,
|
||||
_EGL_MAX_PBUFFER_HEIGHT);
|
||||
break;
|
||||
|
||||
case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER:
|
||||
if (disp->Extensions.KHR_mutable_render_buffer)
|
||||
surface_type |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
|
||||
break;
|
||||
default:
|
||||
key = dri2_to_egl_attribute_map[attrib];
|
||||
if (key != 0)
|
||||
@@ -460,6 +463,7 @@ static const struct dri2_extension_match optional_core_extensions[] = {
|
||||
{ __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
|
||||
{ __DRI2_FLUSH_CONTROL, 1, offsetof(struct dri2_egl_display, flush_control) },
|
||||
{ __DRI2_BLOB, 1, offsetof(struct dri2_egl_display, blob) },
|
||||
{ __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1, offsetof(struct dri2_egl_display, mutable_render_buffer) },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -1317,12 +1321,6 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
|
||||
dri_config = dri2_config->dri_config[1][0];
|
||||
else
|
||||
dri_config = dri2_config->dri_config[0][0];
|
||||
|
||||
/* EGL_WINDOW_BIT is set only when there is a double-buffered dri_config.
|
||||
* This makes sure the back buffer will always be used.
|
||||
*/
|
||||
if (conf->SurfaceType & EGL_WINDOW_BIT)
|
||||
dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
|
||||
}
|
||||
else
|
||||
dri_config = NULL;
|
||||
@@ -1493,6 +1491,8 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
||||
_EGLDisplay *old_disp = NULL;
|
||||
struct dri2_egl_display *old_dri2_dpy = NULL;
|
||||
_EGLContext *old_ctx;
|
||||
_EGLSurface *old_dsurf, *old_rsurf;
|
||||
_EGLSurface *tmp_dsurf, *tmp_rsurf;
|
||||
@@ -1509,6 +1509,11 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (old_ctx) {
|
||||
old_disp = old_ctx->Resource.Display;
|
||||
old_dri2_dpy = dri2_egl_display(old_disp);
|
||||
}
|
||||
|
||||
/* flush before context switch */
|
||||
if (old_ctx)
|
||||
dri2_gl_flush();
|
||||
@@ -1522,31 +1527,30 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
|
||||
|
||||
if (old_dsurf)
|
||||
dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf);
|
||||
|
||||
/* Disable shared buffer mode */
|
||||
if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
|
||||
old_dri2_dpy->vtbl->set_shared_buffer_mode) {
|
||||
old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false);
|
||||
}
|
||||
|
||||
dri2_dpy->core->unbindContext(old_cctx);
|
||||
}
|
||||
|
||||
unbind = (cctx == NULL && ddraw == NULL && rdraw == NULL);
|
||||
|
||||
if (unbind || dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
|
||||
dri2_destroy_surface(drv, disp, old_dsurf);
|
||||
dri2_destroy_surface(drv, disp, old_rsurf);
|
||||
|
||||
if (!unbind)
|
||||
dri2_dpy->ref_count++;
|
||||
if (old_ctx) {
|
||||
EGLDisplay old_disp = _eglGetDisplayHandle(old_ctx->Resource.Display);
|
||||
dri2_destroy_context(drv, disp, old_ctx);
|
||||
dri2_display_release(old_disp);
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
} else {
|
||||
if (!unbind && !dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
|
||||
/* undo the previous _eglBindContext */
|
||||
_eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
|
||||
assert(&dri2_ctx->base == ctx &&
|
||||
tmp_dsurf == dsurf &&
|
||||
tmp_rsurf == rsurf);
|
||||
|
||||
if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
|
||||
old_dri2_dpy->vtbl->set_shared_buffer_mode) {
|
||||
old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
|
||||
}
|
||||
|
||||
_eglPutSurface(dsurf);
|
||||
_eglPutSurface(rsurf);
|
||||
_eglPutContext(ctx);
|
||||
@@ -1561,6 +1565,31 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
|
||||
*/
|
||||
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
||||
}
|
||||
|
||||
dri2_destroy_surface(drv, disp, old_dsurf);
|
||||
dri2_destroy_surface(drv, disp, old_rsurf);
|
||||
|
||||
if (!unbind)
|
||||
dri2_dpy->ref_count++;
|
||||
|
||||
if (old_ctx) {
|
||||
dri2_destroy_context(drv, disp, old_ctx);
|
||||
dri2_display_release(old_disp);
|
||||
}
|
||||
|
||||
if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) &&
|
||||
dri2_dpy->vtbl->set_shared_buffer_mode) {
|
||||
/* Always update the shared buffer mode. This is obviously needed when
|
||||
* the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When
|
||||
* EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the
|
||||
* case where external non-EGL API may have changed window's shared
|
||||
* buffer mode since we last saw it.
|
||||
*/
|
||||
bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER);
|
||||
dri2_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode);
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
__DRIdrawable *
|
||||
|
@@ -67,7 +67,7 @@ struct zwp_linux_dmabuf_v1;
|
||||
|
||||
#include <system/window.h>
|
||||
#include <hardware/gralloc.h>
|
||||
#include <gralloc_drm_handle.h>
|
||||
#include "platform_android_gralloc_drm.h"
|
||||
|
||||
#endif /* HAVE_ANDROID_PLATFORM */
|
||||
|
||||
@@ -153,6 +153,12 @@ struct dri2_egl_display_vtbl {
|
||||
__DRIdrawable *(*get_dri_drawable)(_EGLSurface *surf);
|
||||
|
||||
void (*close_screen_notify)(_EGLDisplay *dpy);
|
||||
|
||||
/* Used in EGL_KHR_mutable_render_buffer to update the native window's
|
||||
* shared buffer mode.
|
||||
*/
|
||||
bool (*set_shared_buffer_mode)(_EGLDisplay *dpy, _EGLSurface *surf,
|
||||
bool mode);
|
||||
};
|
||||
|
||||
struct dri2_egl_display
|
||||
@@ -180,6 +186,7 @@ struct dri2_egl_display
|
||||
const __DRI2blobExtension *blob;
|
||||
const __DRI2rendererQueryExtension *rendererQuery;
|
||||
const __DRI2interopExtension *interop;
|
||||
const __DRImutableRenderBufferDriverExtension *mutable_render_buffer;
|
||||
int fd;
|
||||
|
||||
/* dri2_initialize/dri2_terminate increment/decrement this count, so does
|
||||
|
@@ -37,7 +37,7 @@
|
||||
#include "loader.h"
|
||||
#include "egl_dri2.h"
|
||||
#include "egl_dri2_fallbacks.h"
|
||||
#include "gralloc_drm.h"
|
||||
#include "platform_android_gralloc_drm.h"
|
||||
|
||||
#define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1))
|
||||
|
||||
@@ -293,6 +293,32 @@ droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
droid_set_shared_buffer_mode(_EGLDisplay *disp, _EGLSurface *surf, bool mode)
|
||||
{
|
||||
#if ANDROID_API_LEVEL >= 24
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
|
||||
struct ANativeWindow *window = dri2_surf->window;
|
||||
|
||||
assert(surf->Type == EGL_WINDOW_BIT);
|
||||
assert(_eglSurfaceHasMutableRenderBuffer(&dri2_surf->base));
|
||||
|
||||
_eglLog(_EGL_DEBUG, "%s: mode=%d", __func__, mode);
|
||||
|
||||
if (native_window_set_shared_buffer_mode(window, mode)) {
|
||||
_eglLog(_EGL_WARNING, "failed native_window_set_shared_buffer_mode"
|
||||
"(window=%p, mode=%d)", window, mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
_eglLog(_EGL_FATAL, "%s:%d: internal error: unreachable", __FILE__, __LINE__);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
|
||||
_EGLConfig *conf, void *native_window,
|
||||
@@ -583,6 +609,21 @@ droid_image_get_buffers(__DRIdrawable *driDrawable,
|
||||
if (update_buffers(dri2_surf) < 0)
|
||||
return 0;
|
||||
|
||||
if (_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {
|
||||
if (get_back_bo(dri2_surf) < 0)
|
||||
return 0;
|
||||
|
||||
/* We have dri_image_back because this is a window surface and
|
||||
* get_back_bo() succeeded.
|
||||
*/
|
||||
assert(dri2_surf->dri_image_back);
|
||||
images->back = dri2_surf->dri_image_back;
|
||||
images->image_mask |= __DRI_IMAGE_BUFFER_SHARED;
|
||||
|
||||
/* There exists no accompanying back nor front buffer. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
|
||||
if (get_front_bo(dri2_surf, format) < 0)
|
||||
return 0;
|
||||
@@ -629,6 +670,21 @@ droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
|
||||
if (dri2_surf->base.Type != EGL_WINDOW_BIT)
|
||||
return EGL_TRUE;
|
||||
|
||||
const bool has_mutable_rb = _eglSurfaceHasMutableRenderBuffer(draw);
|
||||
|
||||
/* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* If surface is a single-buffered window, pixmap, or pbuffer surface
|
||||
* for which there is no pending change to the EGL_RENDER_BUFFER
|
||||
* attribute, eglSwapBuffers has no effect.
|
||||
*/
|
||||
if (has_mutable_rb &&
|
||||
draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER &&
|
||||
draw->ActiveRenderBuffer == EGL_SINGLE_BUFFER) {
|
||||
_eglLog(_EGL_DEBUG, "%s: remain in shared buffer mode", __func__);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
|
||||
if (dri2_surf->color_buffers[i].age > 0)
|
||||
dri2_surf->color_buffers[i].age++;
|
||||
@@ -653,6 +709,18 @@ droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
|
||||
|
||||
dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
|
||||
|
||||
/* Update the shared buffer mode */
|
||||
if (has_mutable_rb &&
|
||||
draw->ActiveRenderBuffer != draw->RequestedRenderBuffer) {
|
||||
bool mode = (draw->RequestedRenderBuffer == EGL_SINGLE_BUFFER);
|
||||
_eglLog(_EGL_DEBUG, "%s: change to shared buffer mode %d",
|
||||
__func__, mode);
|
||||
|
||||
if (!droid_set_shared_buffer_mode(disp, draw, mode))
|
||||
return EGL_FALSE;
|
||||
draw->ActiveRenderBuffer = draw->RequestedRenderBuffer;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
@@ -1058,7 +1126,6 @@ droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||
{ HAL_PIXEL_FORMAT_RGBA_8888, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 } },
|
||||
{ HAL_PIXEL_FORMAT_RGBX_8888, { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 } },
|
||||
{ HAL_PIXEL_FORMAT_RGB_565, { 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 } },
|
||||
{ HAL_PIXEL_FORMAT_BGRA_8888, { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 } },
|
||||
};
|
||||
|
||||
unsigned int format_count[ARRAY_SIZE(visuals)] = { 0 };
|
||||
@@ -1126,7 +1193,7 @@ droid_open_device(struct dri2_egl_display *dri2_dpy)
|
||||
GRALLOC_MODULE_PERFORM_GET_DRM_FD,
|
||||
&fd);
|
||||
if (err || fd < 0) {
|
||||
_eglLog(_EGL_WARNING, "fail to get drm fd");
|
||||
_eglLog(_EGL_DEBUG, "fail to get drm fd");
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
@@ -1156,6 +1223,7 @@ static const struct dri2_egl_display_vtbl droid_display_vtbl = {
|
||||
.create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
|
||||
.get_sync_values = dri2_fallback_get_sync_values,
|
||||
.get_dri_drawable = dri2_surface_get_dri_drawable,
|
||||
.set_shared_buffer_mode = droid_set_shared_buffer_mode,
|
||||
};
|
||||
|
||||
static const __DRIdri2LoaderExtension droid_dri2_loader_extension = {
|
||||
@@ -1175,10 +1243,89 @@ static const __DRIimageLoaderExtension droid_image_loader_extension = {
|
||||
.getCapability = droid_get_capability,
|
||||
};
|
||||
|
||||
static void
|
||||
droid_display_shared_buffer(__DRIdrawable *driDrawable, int fence_fd,
|
||||
void *loaderPrivate)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = loaderPrivate;
|
||||
struct ANativeWindowBuffer *old_buffer UNUSED = dri2_surf->buffer;
|
||||
|
||||
if (!_eglSurfaceInSharedBufferMode(&dri2_surf->base)) {
|
||||
_eglLog(_EGL_WARNING, "%s: internal error: buffer is not shared",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fence_fd >= 0) {
|
||||
/* The driver's fence is more recent than the surface's out fence, if it
|
||||
* exists at all. So use the driver's fence.
|
||||
*/
|
||||
if (dri2_surf->out_fence_fd >= 0) {
|
||||
close(dri2_surf->out_fence_fd);
|
||||
dri2_surf->out_fence_fd = -1;
|
||||
}
|
||||
} else if (dri2_surf->out_fence_fd >= 0) {
|
||||
fence_fd = dri2_surf->out_fence_fd;
|
||||
dri2_surf->out_fence_fd = -1;
|
||||
}
|
||||
|
||||
if (dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
|
||||
fence_fd)) {
|
||||
_eglLog(_EGL_WARNING, "%s: ANativeWindow::queueBuffer failed", __func__);
|
||||
close(fence_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
fence_fd = -1;
|
||||
|
||||
if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
|
||||
&fence_fd)) {
|
||||
/* Tear down the surface because it no longer has a back buffer. */
|
||||
struct dri2_egl_display *dri2_dpy =
|
||||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
|
||||
_eglLog(_EGL_WARNING, "%s: ANativeWindow::dequeueBuffer failed", __func__);
|
||||
|
||||
dri2_surf->base.Lost = true;
|
||||
dri2_surf->buffer = NULL;
|
||||
dri2_surf->back = NULL;
|
||||
|
||||
if (dri2_surf->dri_image_back) {
|
||||
dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
|
||||
dri2_surf->dri_image_back = NULL;
|
||||
}
|
||||
|
||||
dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fence_fd < 0)
|
||||
return;
|
||||
|
||||
/* Access to the buffer is controlled by a sync fence. Block on it.
|
||||
*
|
||||
* Ideally, we would submit the fence to the driver, and the driver would
|
||||
* postpone command execution until it signalled. But DRI lacks API for
|
||||
* that (as of 2018-04-11).
|
||||
*
|
||||
* SYNC_IOC_WAIT waits forever if timeout < 0
|
||||
*/
|
||||
sync_wait(fence_fd, -1);
|
||||
close(fence_fd);
|
||||
}
|
||||
|
||||
static const __DRImutableRenderBufferLoaderExtension droid_mutable_render_buffer_extension = {
|
||||
.base = { __DRI_MUTABLE_RENDER_BUFFER_LOADER, 1 },
|
||||
.displaySharedBuffer = droid_display_shared_buffer,
|
||||
};
|
||||
|
||||
static const __DRIextension *droid_dri2_loader_extensions[] = {
|
||||
&droid_dri2_loader_extension.base,
|
||||
&image_lookup_extension.base,
|
||||
&use_invalidate.base,
|
||||
/* No __DRI_MUTABLE_RENDER_BUFFER_LOADER because it requires
|
||||
* __DRI_IMAGE_LOADER.
|
||||
*/
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -1186,9 +1333,82 @@ static const __DRIextension *droid_image_loader_extensions[] = {
|
||||
&droid_image_loader_extension.base,
|
||||
&image_lookup_extension.base,
|
||||
&use_invalidate.base,
|
||||
&droid_mutable_render_buffer_extension.base,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static bool
|
||||
droid_probe_device(_EGLDisplay *dpy)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dpy->DriverData;
|
||||
bool loaded;
|
||||
|
||||
dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
|
||||
if (!dri2_dpy->is_render_node && !gralloc_supports_gem_names()) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: control nodes not supported without GEM name suport in gralloc\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dpy->Options.ForceSoftware)
|
||||
dri2_dpy->driver_name = strdup("kms_swrast");
|
||||
else
|
||||
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
|
||||
|
||||
if (dri2_dpy->driver_name == NULL) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: failed to get driver name");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* render nodes cannot use Gem names, and thus do not support
|
||||
* the __DRI_DRI2_LOADER extension */
|
||||
if (!dri2_dpy->is_render_node) {
|
||||
dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
|
||||
loaded = dri2_load_driver(dpy);
|
||||
} else {
|
||||
dri2_dpy->loader_extensions = droid_image_loader_extensions;
|
||||
loaded = dri2_load_driver_dri3(dpy);
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: failed to load driver");
|
||||
free(dri2_dpy->driver_name);
|
||||
dri2_dpy->driver_name = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
droid_probe_devices(_EGLDisplay *dpy)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dpy->DriverData;
|
||||
const char *name_template = "%s/renderD%d";
|
||||
const int base = 128;
|
||||
const int limit = 64;
|
||||
int minor;
|
||||
|
||||
for (minor = base; minor < base + limit; ++minor) {
|
||||
char *card_path;
|
||||
|
||||
if (asprintf(&card_path, name_template, DRM_DIR_NAME, minor) < 0)
|
||||
continue;
|
||||
|
||||
dri2_dpy->fd = loader_open_device(card_path);
|
||||
free(card_path);
|
||||
if (dri2_dpy->fd < 0)
|
||||
continue;
|
||||
|
||||
if (droid_probe_device(dpy))
|
||||
return true;
|
||||
|
||||
close(dri2_dpy->fd);
|
||||
dri2_dpy->fd = -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
|
||||
{
|
||||
@@ -1196,10 +1416,6 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
|
||||
const char *err;
|
||||
int ret;
|
||||
|
||||
/* Not supported yet */
|
||||
if (disp->Options.ForceSoftware)
|
||||
return EGL_FALSE;
|
||||
|
||||
loader_set_logger(_eglLog);
|
||||
|
||||
dri2_dpy = calloc(1, sizeof(*dri2_dpy));
|
||||
@@ -1217,35 +1433,16 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
|
||||
disp->DriverData = (void *) dri2_dpy;
|
||||
|
||||
dri2_dpy->fd = droid_open_device(dri2_dpy);
|
||||
if (dri2_dpy->fd < 0) {
|
||||
err = "DRI2: failed to open device";
|
||||
if (dri2_dpy->fd >= 0 && !droid_probe_device(disp)) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: Failed to load %s driver",
|
||||
disp->Options.ForceSoftware ? "software" : "hardware");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
|
||||
if (dri2_dpy->driver_name == NULL) {
|
||||
err = "DRI2: failed to get driver name";
|
||||
} else if (!droid_probe_devices(disp)) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: Failed to load %s driver",
|
||||
disp->Options.ForceSoftware ? "software" : "hardware");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
|
||||
|
||||
/* render nodes cannot use Gem names, and thus do not support
|
||||
* the __DRI_DRI2_LOADER extension */
|
||||
if (!dri2_dpy->is_render_node) {
|
||||
dri2_dpy->loader_extensions = droid_dri2_loader_extensions;
|
||||
if (!dri2_load_driver(disp)) {
|
||||
err = "DRI2: failed to load driver";
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
dri2_dpy->loader_extensions = droid_image_loader_extensions;
|
||||
if (!dri2_load_driver_dri3(disp)) {
|
||||
err = "DRI3: failed to load driver";
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dri2_create_screen(disp)) {
|
||||
err = "DRI2: failed to create screen";
|
||||
goto cleanup;
|
||||
@@ -1264,11 +1461,6 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
|
||||
*/
|
||||
dri2_setup_swap_interval(disp, 1);
|
||||
|
||||
if (!droid_add_configs_for_visuals(drv, disp)) {
|
||||
err = "DRI2: failed to add configs";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
disp->Extensions.ANDROID_framebuffer_target = EGL_TRUE;
|
||||
disp->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
|
||||
disp->Extensions.ANDROID_recordable = EGL_TRUE;
|
||||
@@ -1277,6 +1469,20 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
|
||||
disp->Extensions.KHR_partial_update = EGL_TRUE;
|
||||
#endif
|
||||
disp->Extensions.KHR_image = EGL_TRUE;
|
||||
#if ANDROID_API_LEVEL >= 24
|
||||
if (dri2_dpy->mutable_render_buffer &&
|
||||
dri2_dpy->loader_extensions == droid_image_loader_extensions) {
|
||||
disp->Extensions.KHR_mutable_render_buffer = EGL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create configs *after* enabling extensions because presence of DRI
|
||||
* driver extensions can affect the capabilities of EGLConfigs.
|
||||
*/
|
||||
if (!droid_add_configs_for_visuals(drv, disp)) {
|
||||
err = "DRI2: failed to add configs";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
* initialization.
|
||||
|
45
src/egl/drivers/dri2/platform_android_gralloc_drm.h
Normal file
45
src/egl/drivers/dri2/platform_android_gralloc_drm.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc. 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 (including the next
|
||||
* paragraph) 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef HAS_GRALLOC_DRM_HEADERS
|
||||
|
||||
#include <gralloc_drm.h>
|
||||
#include <gralloc_drm_handle.h>
|
||||
|
||||
static inline bool gralloc_supports_gem_names(void) { return true; }
|
||||
|
||||
#else
|
||||
|
||||
#define GRALLOC_MODULE_PERFORM_GET_DRM_FD 0x0FD4DEAD
|
||||
|
||||
static inline int gralloc_drm_get_gem_handle(buffer_handle_t handle)
|
||||
{
|
||||
return 0; /* Not supported, return invalid handle. */
|
||||
}
|
||||
|
||||
static inline bool gralloc_supports_gem_names(void) { return false; }
|
||||
|
||||
#endif
|
@@ -509,6 +509,7 @@ _eglCreateExtensionsString(_EGLDisplay *dpy)
|
||||
_EGL_CHECK_EXTENSION(KHR_image);
|
||||
_EGL_CHECK_EXTENSION(KHR_image_base);
|
||||
_EGL_CHECK_EXTENSION(KHR_image_pixmap);
|
||||
_EGL_CHECK_EXTENSION(KHR_mutable_render_buffer);
|
||||
_EGL_CHECK_EXTENSION(KHR_no_config_context);
|
||||
_EGL_CHECK_EXTENSION(KHR_partial_update);
|
||||
_EGL_CHECK_EXTENSION(KHR_reusable_sync);
|
||||
|
@@ -272,6 +272,7 @@ static const struct {
|
||||
EGLBoolean
|
||||
_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
|
||||
{
|
||||
_EGLDisplay *disp = conf->Display;
|
||||
EGLint i, attr, val;
|
||||
EGLBoolean valid = EGL_TRUE;
|
||||
|
||||
@@ -340,6 +341,8 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
|
||||
EGL_VG_ALPHA_FORMAT_PRE_BIT |
|
||||
EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
|
||||
EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
|
||||
if (disp->Extensions.KHR_mutable_render_buffer)
|
||||
mask |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
|
||||
break;
|
||||
case EGL_RENDERABLE_TYPE:
|
||||
case EGL_CONFORMANT:
|
||||
|
@@ -588,7 +588,6 @@ _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
|
||||
_eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
|
||||
ctx->ClientAPI = api;
|
||||
ctx->Config = conf;
|
||||
ctx->WindowRenderBuffer = EGL_NONE;
|
||||
ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||
|
||||
ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
|
||||
@@ -620,15 +619,42 @@ static EGLint
|
||||
_eglQueryContextRenderBuffer(_EGLContext *ctx)
|
||||
{
|
||||
_EGLSurface *surf = ctx->DrawSurface;
|
||||
EGLint rb;
|
||||
|
||||
/* From the EGL 1.5 spec:
|
||||
*
|
||||
* - If the context is not bound to a surface, then EGL_NONE will be
|
||||
* returned.
|
||||
*/
|
||||
if (!surf)
|
||||
return EGL_NONE;
|
||||
if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
|
||||
rb = ctx->WindowRenderBuffer;
|
||||
else
|
||||
rb = surf->RenderBuffer;
|
||||
return rb;
|
||||
|
||||
switch (surf->Type) {
|
||||
default:
|
||||
unreachable("bad EGLSurface type");
|
||||
case EGL_PIXMAP_BIT:
|
||||
/* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER
|
||||
* will be returned.
|
||||
*/
|
||||
return EGL_SINGLE_BUFFER;
|
||||
case EGL_PBUFFER_BIT:
|
||||
/* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER
|
||||
* will be returned.
|
||||
*/
|
||||
return EGL_BACK_BUFFER;
|
||||
case EGL_WINDOW_BIT:
|
||||
/* - If the context is bound to a window surface, then either
|
||||
* EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value
|
||||
* returned depends on both the buffer requested by the setting of the
|
||||
* EGL_RENDER_BUFFER property of the surface [...], and on the client
|
||||
* API (not all client APIs support single-buffer Rendering to window
|
||||
* surfaces). Some client APIs allow control of whether rendering goes
|
||||
* to the front or back buffer. This client API-specific choice is not
|
||||
* reflected in the returned value, which only describes the buffer
|
||||
* that will be rendered to by default if not overridden by the client
|
||||
* API.
|
||||
*/
|
||||
return surf->ActiveRenderBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -65,9 +65,6 @@ struct _egl_context
|
||||
EGLint ContextPriority;
|
||||
EGLBoolean NoError;
|
||||
EGLint ReleaseBehavior;
|
||||
|
||||
/* The real render buffer when a window surface is bound */
|
||||
EGLint WindowRenderBuffer;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -127,6 +127,7 @@ struct _egl_extensions
|
||||
EGLBoolean KHR_image;
|
||||
EGLBoolean KHR_image_base;
|
||||
EGLBoolean KHR_image_pixmap;
|
||||
EGLBoolean KHR_mutable_render_buffer;
|
||||
EGLBoolean KHR_no_config_context;
|
||||
EGLBoolean KHR_partial_update;
|
||||
EGLBoolean KHR_reusable_sync;
|
||||
|
@@ -122,7 +122,13 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->RenderBuffer = val;
|
||||
surf->RequestedRenderBuffer = val;
|
||||
if (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) {
|
||||
/* Unlike normal EGLSurfaces, one with a mutable render buffer
|
||||
* uses the application-chosen render buffer.
|
||||
*/
|
||||
surf->ActiveRenderBuffer = val;
|
||||
}
|
||||
break;
|
||||
case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
|
||||
if (!dpy->Extensions.NV_post_sub_buffer ||
|
||||
@@ -285,7 +291,8 @@ _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
|
||||
surf->TextureTarget = EGL_NO_TEXTURE;
|
||||
surf->MipmapTexture = EGL_FALSE;
|
||||
surf->LargestPbuffer = EGL_FALSE;
|
||||
surf->RenderBuffer = renderBuffer;
|
||||
surf->RequestedRenderBuffer = renderBuffer;
|
||||
surf->ActiveRenderBuffer = renderBuffer;
|
||||
surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
|
||||
surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
|
||||
surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
|
||||
@@ -358,7 +365,35 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
|
||||
*value = surface->SwapBehavior;
|
||||
break;
|
||||
case EGL_RENDER_BUFFER:
|
||||
*value = surface->RenderBuffer;
|
||||
/* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* Querying EGL_RENDER_BUFFER returns the buffer which client API
|
||||
* rendering is requested to use. For a window surface, this is the
|
||||
* attribute value specified when the surface was created or last set
|
||||
* via eglSurfaceAttrib.
|
||||
*
|
||||
* In other words, querying a window surface returns the value most
|
||||
* recently *requested* by the user.
|
||||
*
|
||||
* The paragraph continues in the EGL 1.5 spec (2014.08.27):
|
||||
*
|
||||
* For a pbuffer surface, it is always EGL_BACK_BUFFER . For a pixmap
|
||||
* surface, it is always EGL_SINGLE_BUFFER . To determine the actual
|
||||
* buffer being rendered to by a context, call eglQueryContext.
|
||||
*/
|
||||
switch (surface->Type) {
|
||||
default:
|
||||
unreachable("bad EGLSurface type");
|
||||
case EGL_WINDOW_BIT:
|
||||
*value = surface->RequestedRenderBuffer;
|
||||
break;
|
||||
case EGL_PBUFFER_BIT:
|
||||
*value = EGL_BACK_BUFFER;
|
||||
break;
|
||||
case EGL_PIXMAP_BIT:
|
||||
*value = EGL_SINGLE_BUFFER;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EGL_PIXEL_ASPECT_RATIO:
|
||||
*value = surface->AspectRatio;
|
||||
@@ -450,6 +485,31 @@ _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
|
||||
break;
|
||||
surface->MultisampleResolve = value;
|
||||
break;
|
||||
case EGL_RENDER_BUFFER:
|
||||
if (!dpy->Extensions.KHR_mutable_render_buffer) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
/* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* If attribute is EGL_RENDER_BUFFER, and the EGL_SURFACE_TYPE
|
||||
* attribute of the EGLConfig used to create surface does not contain
|
||||
* EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, [...] an EGL_BAD_MATCH error is
|
||||
* generated [...].
|
||||
*/
|
||||
if (!(surface->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR)) {
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
surface->RequestedRenderBuffer = value;
|
||||
break;
|
||||
case EGL_SWAP_BEHAVIOR:
|
||||
switch (value) {
|
||||
case EGL_BUFFER_DESTROYED:
|
||||
@@ -551,3 +611,18 @@ _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
||||
{
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf)
|
||||
{
|
||||
return surf->Type == EGL_WINDOW_BIT &&
|
||||
surf->Config &&
|
||||
(surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR);
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglSurfaceInSharedBufferMode(_EGLSurface *surf)
|
||||
{
|
||||
return _eglSurfaceHasMutableRenderBuffer(surf) &&
|
||||
surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER;
|
||||
}
|
||||
|
@@ -67,7 +67,59 @@ struct _egl_surface
|
||||
EGLenum TextureTarget;
|
||||
EGLBoolean MipmapTexture;
|
||||
EGLBoolean LargestPbuffer;
|
||||
EGLenum RenderBuffer;
|
||||
|
||||
/**
|
||||
* Value of EGL_RENDER_BUFFER selected at creation.
|
||||
*
|
||||
* The user may select, for window surfaces, the EGL_RENDER_BUFFER through
|
||||
* the attribute list of eglCreateWindowSurface(). The EGL spec allows the
|
||||
* implementation to ignore request, though; hence why we maintain both
|
||||
* RequestedRenderBuffer and ActiveRenderBuffer. For pbuffer and pixmap
|
||||
* surfaces, the EGL spec hard-codes the EGL_RENDER_BUFFER value and the
|
||||
* user must not provide it in the attribute list.
|
||||
*
|
||||
* Normally, the attribute is immutable and after surface creation.
|
||||
* However, EGL_KHR_mutable_render_buffer allows the user to change it in
|
||||
* window surfaces via eglSurfaceAttrib, in which case
|
||||
* eglQuerySurface(EGL_RENDER_BUFFER) will immediately afterwards return
|
||||
* the requested value but the actual render buffer used by the context
|
||||
* does not change until completion of the next eglSwapBuffers call.
|
||||
*
|
||||
* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* Querying EGL_RENDER_BUFFER returns the buffer which client API
|
||||
* rendering is requested to use. For a window surface, this is the
|
||||
* attribute value specified when the surface was created or last set
|
||||
* via eglSurfaceAttrib.
|
||||
*
|
||||
* eglQueryContext(EGL_RENDER_BUFFER) ignores this.
|
||||
*/
|
||||
EGLenum RequestedRenderBuffer;
|
||||
|
||||
/**
|
||||
* The EGL_RENDER_BUFFER in use by the context.
|
||||
*
|
||||
* This is valid only when bound as the draw surface. This may differ from
|
||||
* the RequestedRenderBuffer.
|
||||
*
|
||||
* Refer to eglQueryContext(EGL_RENDER_BUFFER) in the EGL spec.
|
||||
* eglQuerySurface(EGL_RENDER_BUFFER) ignores this.
|
||||
*
|
||||
* If a window surface is bound as the draw surface and has a pending,
|
||||
* user-requested change to EGL_RENDER_BUFFER, then the next eglSwapBuffers
|
||||
* will flush the pending change. (The flush of EGL_RENDER_BUFFER state may
|
||||
* occur without the implicit glFlush induced by eglSwapBuffers). The spec
|
||||
* requires that the flush occur at that time and nowhere else. During the
|
||||
* state-flush, we copy RequestedRenderBuffer to ActiveRenderBuffer.
|
||||
*
|
||||
* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* If [...] there is a pending change to the EGL_RENDER_BUFFER
|
||||
* attribute, eglSwapBuffers performs an implicit flush operation on the
|
||||
* context and effects the attribute change.
|
||||
*/
|
||||
EGLenum ActiveRenderBuffer;
|
||||
|
||||
EGLenum VGAlphaFormat;
|
||||
EGLenum VGColorspace;
|
||||
EGLenum GLColorspace;
|
||||
@@ -124,6 +176,11 @@ _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLin
|
||||
extern EGLBoolean
|
||||
_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSurfaceInSharedBufferMode(_EGLSurface *surf);
|
||||
|
||||
/**
|
||||
* Increment reference count for the surface.
|
||||
|
@@ -59,6 +59,12 @@ GALLIUM_COMMON_LIB_DEPS += \
|
||||
$(LIBDRM_LIBS)
|
||||
endif
|
||||
|
||||
if HAVE_PLATFORM_ANDROID
|
||||
GALLIUM_COMMON_LIB_DEPS += \
|
||||
$(ANDROID_LIBS) \
|
||||
$(BACKTRACE_LIBS)
|
||||
endif
|
||||
|
||||
GALLIUM_WINSYS_CFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/include \
|
||||
|
@@ -13,6 +13,7 @@ AM_CFLAGS = \
|
||||
$(MSVC2013_COMPAT_CFLAGS)
|
||||
|
||||
AM_CXXFLAGS = \
|
||||
$(GALLIUM_CFLAGS) \
|
||||
$(VISIBILITY_CXXFLAGS) \
|
||||
$(MSVC2013_COMPAT_CXXFLAGS)
|
||||
|
||||
@@ -21,6 +22,14 @@ libgallium_la_SOURCES = \
|
||||
$(NIR_SOURCES) \
|
||||
$(GENERATED_SOURCES)
|
||||
|
||||
if HAVE_PLATFORM_ANDROID
|
||||
# Android's libbacktrace headers required C++11, but the Android toolchain (at
|
||||
# least in the Chrome OS SDK) does not enable C++11 by default.
|
||||
AM_CXXFLAGS += $(CXX11_CXXFLAGS)
|
||||
|
||||
libgallium_la_SOURCES += util/u_debug_stack_android.cpp
|
||||
endif
|
||||
|
||||
if HAVE_LIBDRM
|
||||
|
||||
AM_CFLAGS += \
|
||||
@@ -37,7 +46,6 @@ AM_CFLAGS += \
|
||||
$(LLVM_CFLAGS)
|
||||
|
||||
AM_CXXFLAGS += \
|
||||
$(GALLIUM_CFLAGS) \
|
||||
$(LLVM_CXXFLAGS)
|
||||
|
||||
libgallium_la_SOURCES += \
|
||||
|
@@ -528,7 +528,7 @@ int virgl_encoder_inline_write(struct virgl_context *ctx,
|
||||
|
||||
left_bytes = size;
|
||||
while (left_bytes) {
|
||||
if (ctx->cbuf->cdw + 12 > VIRGL_MAX_CMDBUF_DWORDS)
|
||||
if (ctx->cbuf->cdw + 12 >= VIRGL_MAX_CMDBUF_DWORDS)
|
||||
ctx->base.flush(&ctx->base, NULL, 0);
|
||||
|
||||
thispass = (VIRGL_MAX_CMDBUF_DWORDS - ctx->cbuf->cdw - 12) * 4;
|
||||
|
@@ -274,7 +274,7 @@ dri_fill_in_modes(struct dri_screen *screen)
|
||||
depth_buffer_factor, back_buffer_modes,
|
||||
ARRAY_SIZE(back_buffer_modes),
|
||||
msaa_modes, 1,
|
||||
GL_TRUE, !mixed_color_depth);
|
||||
GL_TRUE, !mixed_color_depth, GL_FALSE);
|
||||
configs = driConcatConfigs(configs, new_configs);
|
||||
|
||||
/* Multi-sample configs without an accumulation buffer. */
|
||||
@@ -284,7 +284,7 @@ dri_fill_in_modes(struct dri_screen *screen)
|
||||
depth_buffer_factor, back_buffer_modes,
|
||||
ARRAY_SIZE(back_buffer_modes),
|
||||
msaa_modes+1, num_msaa_modes-1,
|
||||
GL_FALSE, !mixed_color_depth);
|
||||
GL_FALSE, !mixed_color_depth, GL_FALSE);
|
||||
configs = driConcatConfigs(configs, new_configs);
|
||||
}
|
||||
}
|
||||
|
@@ -26,8 +26,10 @@
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#if !defined(ANDROID) || ANDROID_API_LEVEL >= 26
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_format.h"
|
||||
@@ -83,6 +85,7 @@ dri_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if !defined(ANDROID) || ANDROID_API_LEVEL >= 26
|
||||
static char *
|
||||
alloc_shm(struct dri_sw_displaytarget *dri_sw_dt, unsigned size)
|
||||
{
|
||||
@@ -101,6 +104,7 @@ alloc_shm(struct dri_sw_displaytarget *dri_sw_dt, unsigned size)
|
||||
|
||||
return addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct sw_displaytarget *
|
||||
dri_sw_displaytarget_create(struct sw_winsys *winsys,
|
||||
@@ -131,8 +135,11 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
|
||||
size = dri_sw_dt->stride * nblocksy;
|
||||
|
||||
dri_sw_dt->shmid = -1;
|
||||
|
||||
#if !defined(ANDROID) || ANDROID_API_LEVEL >= 26
|
||||
if (ws->lf->put_image_shm)
|
||||
dri_sw_dt->data = alloc_shm(dri_sw_dt, size);
|
||||
#endif
|
||||
|
||||
if(!dri_sw_dt->data)
|
||||
dri_sw_dt->data = align_malloc(size, alignment);
|
||||
@@ -156,8 +163,10 @@ dri_sw_displaytarget_destroy(struct sw_winsys *ws,
|
||||
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
|
||||
|
||||
if (dri_sw_dt->shmid >= 0) {
|
||||
#if !defined(ANDROID) || ANDROID_API_LEVEL >= 26
|
||||
shmdt(dri_sw_dt->data);
|
||||
shmctl(dri_sw_dt->shmid, IPC_RMID, 0);
|
||||
#endif
|
||||
} else {
|
||||
align_free(dri_sw_dt->data);
|
||||
}
|
||||
|
@@ -164,7 +164,10 @@ VULKAN_LIB_DEPS = \
|
||||
-lm
|
||||
|
||||
if HAVE_PLATFORM_ANDROID
|
||||
VULKAN_CPPFLAGS += $(ANDROID_CPPFLAGS)
|
||||
VULKAN_CPPFLAGS += \
|
||||
$(ANDROID_CPPFLAGS) \
|
||||
-DVK_USE_PLATFORM_ANDROID_KHR
|
||||
|
||||
VULKAN_CFLAGS += $(ANDROID_CFLAGS)
|
||||
VULKAN_LIB_DEPS += $(ANDROID_LIBS)
|
||||
VULKAN_SOURCES += $(VULKAN_ANDROID_FILES)
|
||||
|
@@ -180,7 +180,7 @@ anv_image_from_gralloc(VkDevice device_h,
|
||||
goto fail_create;
|
||||
|
||||
if (bo->size < image->size) {
|
||||
result = vk_errorf(device, device->instance,
|
||||
result = vk_errorf(device->instance, device,
|
||||
VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
|
||||
"dma-buf from VkNativeBufferANDROID is too small for "
|
||||
"VkImage: %"PRIu64"B < %"PRIu64"B",
|
||||
|
@@ -81,6 +81,8 @@ setupLoaderExtensions(__DRIscreen *psp,
|
||||
psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i];
|
||||
if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0)
|
||||
psp->image.loader = (__DRIimageLoaderExtension *) extensions[i];
|
||||
if (strcmp(extensions[i]->name, __DRI_MUTABLE_RENDER_BUFFER_LOADER) == 0)
|
||||
psp->mutableRenderBuffer.loader = (__DRImutableRenderBufferLoaderExtension *) extensions[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -216,6 +216,10 @@ struct __DRIscreenRec {
|
||||
const __DRIimageLoaderExtension *loader;
|
||||
} image;
|
||||
|
||||
struct {
|
||||
const __DRImutableRenderBufferLoaderExtension *loader;
|
||||
} mutableRenderBuffer;
|
||||
|
||||
driOptionCache optionInfo;
|
||||
driOptionCache optionCache;
|
||||
|
||||
|
@@ -147,7 +147,10 @@ driGetRendererString( char * buffer, const char * hardware_name,
|
||||
* \param color_depth_match Whether the color depth must match the zs depth
|
||||
* This forces 32-bit color to have 24-bit depth, and
|
||||
* 16-bit color to have 16-bit depth.
|
||||
*
|
||||
* \param mutable_render_buffer Enable __DRI_ATTRIB_MUTABLE_RENDER_BUFFER,
|
||||
* which translates to
|
||||
* EGL_MUTABLE_RENDER_BUFFER_BIT_KHR.
|
||||
*
|
||||
* \returns
|
||||
* Pointer to any array of pointers to the \c __DRIconfig structures created
|
||||
* for the specified formats. If there is an error, \c NULL is returned.
|
||||
@@ -160,7 +163,8 @@ driCreateConfigs(mesa_format format,
|
||||
unsigned num_depth_stencil_bits,
|
||||
const GLenum * db_modes, unsigned num_db_modes,
|
||||
const uint8_t * msaa_samples, unsigned num_msaa_modes,
|
||||
GLboolean enable_accum, GLboolean color_depth_match)
|
||||
GLboolean enable_accum, GLboolean color_depth_match,
|
||||
GLboolean mutable_render_buffer)
|
||||
{
|
||||
static const uint32_t masks_table[][4] = {
|
||||
/* MESA_FORMAT_B5G6R5_UNORM */
|
||||
@@ -325,6 +329,7 @@ driCreateConfigs(mesa_format format,
|
||||
|
||||
modes->yInverted = GL_TRUE;
|
||||
modes->sRGBCapable = is_srgb;
|
||||
modes->mutableRenderBuffer = mutable_render_buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -409,6 +414,7 @@ static const struct { unsigned int attrib, offset; } attribMap[] = {
|
||||
__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets),
|
||||
__ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
|
||||
__ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable),
|
||||
__ATTRIB(__DRI_ATTRIB_MUTABLE_RENDER_BUFFER, mutableRenderBuffer),
|
||||
|
||||
/* The struct field doesn't matter here, these are handled by the
|
||||
* switch in driGetConfigAttribIndex. We need them in the array
|
||||
|
@@ -45,7 +45,8 @@ driCreateConfigs(mesa_format format,
|
||||
unsigned num_depth_stencil_bits,
|
||||
const GLenum * db_modes, unsigned num_db_modes,
|
||||
const uint8_t * msaa_samples, unsigned num_msaa_modes,
|
||||
GLboolean enable_accum, GLboolean color_depth_match);
|
||||
GLboolean enable_accum, GLboolean color_depth_match,
|
||||
GLboolean mutable_render_buffer);
|
||||
|
||||
__DRIconfig **driConcatConfigs(__DRIconfig **a,
|
||||
__DRIconfig **b);
|
||||
|
@@ -1094,7 +1094,7 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
|
||||
num_depth_stencil_bits,
|
||||
back_buffer_modes, 2,
|
||||
singlesample_samples, 1,
|
||||
false, false);
|
||||
false, false, false);
|
||||
configs = driConcatConfigs(configs, new_configs);
|
||||
}
|
||||
|
||||
@@ -1116,7 +1116,7 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
|
||||
depth_bits, stencil_bits, 1,
|
||||
back_buffer_modes, 1,
|
||||
singlesample_samples, 1,
|
||||
true, false);
|
||||
true, false, false);
|
||||
configs = driConcatConfigs(configs, new_configs);
|
||||
}
|
||||
|
||||
|
@@ -239,6 +239,35 @@ intel_flush_front(struct gl_context *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
brw_display_shared_buffer(struct brw_context *brw)
|
||||
{
|
||||
__DRIcontext *dri_context = brw->driContext;
|
||||
__DRIdrawable *dri_drawable = dri_context->driDrawablePriv;
|
||||
__DRIscreen *dri_screen = brw->screen->driScrnPriv;
|
||||
int fence_fd = -1;
|
||||
|
||||
if (!brw->is_shared_buffer_bound)
|
||||
return;
|
||||
|
||||
if (!brw->is_shared_buffer_dirty)
|
||||
return;
|
||||
|
||||
if (brw->screen->has_exec_fence) {
|
||||
/* This function is always called during a flush operation, so there is
|
||||
* no need to flush again here. But we want to provide a fence_fd to the
|
||||
* loader, and a redundant flush is the easiest way to acquire one.
|
||||
*/
|
||||
if (intel_batchbuffer_flush_fence(brw, -1, &fence_fd))
|
||||
return;
|
||||
}
|
||||
|
||||
dri_screen->mutableRenderBuffer.loader
|
||||
->displaySharedBuffer(dri_drawable, fence_fd,
|
||||
dri_drawable->loaderPrivate);
|
||||
brw->is_shared_buffer_dirty = false;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_glFlush(struct gl_context *ctx)
|
||||
{
|
||||
@@ -246,7 +275,7 @@ intel_glFlush(struct gl_context *ctx)
|
||||
|
||||
intel_batchbuffer_flush(brw);
|
||||
intel_flush_front(ctx);
|
||||
|
||||
brw_display_shared_buffer(brw);
|
||||
brw->need_flush_throttle = true;
|
||||
}
|
||||
|
||||
@@ -909,7 +938,9 @@ brwCreateContext(gl_api api,
|
||||
brw->screen = screen;
|
||||
brw->bufmgr = screen->bufmgr;
|
||||
|
||||
brw->has_hiz = devinfo->has_hiz_and_separate_stencil;
|
||||
/* Braswell has hiz issues, disable it. */
|
||||
brw->has_hiz = devinfo->has_hiz_and_separate_stencil &&
|
||||
screen->deviceID != 0x22B1;
|
||||
brw->has_separate_stencil = devinfo->has_hiz_and_separate_stencil;
|
||||
|
||||
brw->has_swizzling = screen->hw_has_swizzling;
|
||||
@@ -1452,6 +1483,11 @@ intel_prepare_render(struct brw_context *brw)
|
||||
*/
|
||||
if (_mesa_is_front_buffer_drawing(ctx->DrawBuffer))
|
||||
brw->front_buffer_dirty = true;
|
||||
|
||||
if (brw->is_shared_buffer_bound) {
|
||||
/* Subsequent rendering will probably dirty the shared buffer. */
|
||||
brw->is_shared_buffer_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1685,8 +1721,12 @@ intel_update_image_buffer(struct brw_context *intel,
|
||||
else
|
||||
last_mt = rb->singlesample_mt;
|
||||
|
||||
if (last_mt && last_mt->bo == buffer->bo)
|
||||
if (last_mt && last_mt->bo == buffer->bo) {
|
||||
if (buffer_type == __DRI_IMAGE_BUFFER_SHARED) {
|
||||
intel_miptree_make_shareable(intel, last_mt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only allow internal compression if samples == 0. For multisampled
|
||||
* window system buffers, the only thing the single-sampled buffer is used
|
||||
@@ -1715,6 +1755,35 @@ intel_update_image_buffer(struct brw_context *intel,
|
||||
rb->Base.Base.NumSamples > 1) {
|
||||
intel_renderbuffer_upsample(intel, rb);
|
||||
}
|
||||
|
||||
if (buffer_type == __DRI_IMAGE_BUFFER_SHARED) {
|
||||
/* The compositor and the application may access this image
|
||||
* concurrently. The display hardware may even scanout the image while
|
||||
* the GPU is rendering to it. Aux surfaces cause difficulty with
|
||||
* concurrent access, so permanently disable aux for this miptree.
|
||||
*
|
||||
* Perhaps we could improve overall application performance by
|
||||
* re-enabling the aux surface when EGL_RENDER_BUFFER transitions to
|
||||
* EGL_BACK_BUFFER, then disabling it again when EGL_RENDER_BUFFER
|
||||
* returns to EGL_SINGLE_BUFFER. I expect the wins and losses with this
|
||||
* approach to be highly dependent on the application's GL usage.
|
||||
*
|
||||
* I [chadv] expect clever disabling/reenabling to be counterproductive
|
||||
* in the use cases I care about: applications that render nearly
|
||||
* realtime handwriting to the surface while possibly undergiong
|
||||
* simultaneously scanout as a display plane. The app requires low
|
||||
* render latency. Even though the app spends most of its time in
|
||||
* shared-buffer mode, it also frequently transitions between
|
||||
* shared-buffer (EGL_SINGLE_BUFFER) and double-buffer (EGL_BACK_BUFFER)
|
||||
* mode. Visual sutter during the transitions should be avoided.
|
||||
*
|
||||
* In this case, I [chadv] believe reducing the GPU workload at
|
||||
* shared-buffer/double-buffer transitions would offer a smoother app
|
||||
* experience than any savings due to aux compression. But I've
|
||||
* collected no data to prove my theory.
|
||||
*/
|
||||
intel_miptree_make_shareable(intel, mt);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1775,4 +1844,19 @@ intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
|
||||
images.back,
|
||||
__DRI_IMAGE_BUFFER_BACK);
|
||||
}
|
||||
|
||||
if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) {
|
||||
assert(images.image_mask == __DRI_IMAGE_BUFFER_SHARED);
|
||||
drawable->w = images.back->width;
|
||||
drawable->h = images.back->height;
|
||||
intel_update_image_buffer(brw,
|
||||
drawable,
|
||||
back_rb,
|
||||
images.back,
|
||||
__DRI_IMAGE_BUFFER_SHARED);
|
||||
brw->is_shared_buffer_bound = true;
|
||||
} else {
|
||||
brw->is_shared_buffer_bound = false;
|
||||
brw->is_shared_buffer_dirty = false;
|
||||
}
|
||||
}
|
||||
|
@@ -790,6 +790,18 @@ struct brw_context
|
||||
*/
|
||||
bool front_buffer_dirty;
|
||||
|
||||
/**
|
||||
* True if the __DRIdrawable's current __DRIimageBufferMask is
|
||||
* __DRI_IMAGE_BUFFER_SHARED.
|
||||
*/
|
||||
bool is_shared_buffer_bound;
|
||||
|
||||
/**
|
||||
* True if a shared buffer is bound and it has received any rendering since
|
||||
* the previous __DRImutableRenderBufferLoaderExtension::displaySharedBuffer().
|
||||
*/
|
||||
bool is_shared_buffer_dirty;
|
||||
|
||||
/** Framerate throttling: @{ */
|
||||
struct brw_bo *throttle_batch[2];
|
||||
|
||||
|
@@ -1588,12 +1588,17 @@ static const __DRI2blobExtension intelBlobExtension = {
|
||||
.set_cache_funcs = brw_set_cache_funcs
|
||||
};
|
||||
|
||||
static const __DRImutableRenderBufferDriverExtension intelMutableRenderBufferExtension = {
|
||||
.base = { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1 },
|
||||
};
|
||||
|
||||
static const __DRIextension *screenExtensions[] = {
|
||||
&intelTexBufferExtension.base,
|
||||
&intelFenceExtension.base,
|
||||
&intelFlushExtension.base,
|
||||
&intelImageExtension.base,
|
||||
&intelRendererQueryExtension.base,
|
||||
&intelMutableRenderBufferExtension.base,
|
||||
&dri2ConfigQueryExtension.base,
|
||||
&dri2NoErrorExtension.base,
|
||||
&intelBlobExtension.base,
|
||||
@@ -1606,6 +1611,7 @@ static const __DRIextension *intelRobustScreenExtensions[] = {
|
||||
&intelFlushExtension.base,
|
||||
&intelImageExtension.base,
|
||||
&intelRendererQueryExtension.base,
|
||||
&intelMutableRenderBufferExtension.base,
|
||||
&dri2ConfigQueryExtension.base,
|
||||
&dri2Robustness.base,
|
||||
&dri2NoErrorExtension.base,
|
||||
@@ -2159,7 +2165,9 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
|
||||
bool allow_rgb10_configs = driQueryOptionb(&screen->optionCache,
|
||||
"allow_rgb10_configs");
|
||||
|
||||
/* Generate singlesample configs without accumulation buffer. */
|
||||
/* Generate singlesample configs, each without accumulation buffer
|
||||
* and with EGL_MUTABLE_RENDER_BUFFER_BIT_KHR.
|
||||
*/
|
||||
for (unsigned i = 0; i < num_formats; i++) {
|
||||
__DRIconfig **new_configs;
|
||||
int num_depth_stencil_bits = 2;
|
||||
@@ -2195,7 +2203,8 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
|
||||
num_depth_stencil_bits,
|
||||
back_buffer_modes, 2,
|
||||
singlesample_samples, 1,
|
||||
false, false);
|
||||
false, false,
|
||||
/*mutable_render_buffer*/ true);
|
||||
configs = driConcatConfigs(configs, new_configs);
|
||||
}
|
||||
|
||||
@@ -2222,7 +2231,7 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
|
||||
depth_bits, stencil_bits, 1,
|
||||
back_buffer_modes, 1,
|
||||
singlesample_samples, 1,
|
||||
true, false);
|
||||
true, false, false);
|
||||
configs = driConcatConfigs(configs, new_configs);
|
||||
}
|
||||
|
||||
@@ -2289,7 +2298,7 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
|
||||
back_buffer_modes, 1,
|
||||
multisample_samples,
|
||||
num_msaa_modes,
|
||||
false, false);
|
||||
false, false, false);
|
||||
configs = driConcatConfigs(configs, new_configs);
|
||||
}
|
||||
|
||||
|
@@ -78,7 +78,7 @@ nouveau_get_configs(uint32_t chipset)
|
||||
ARRAY_SIZE(back_buffer_modes),
|
||||
msaa_samples,
|
||||
ARRAY_SIZE(msaa_samples),
|
||||
GL_TRUE, chipset < 0x10);
|
||||
GL_TRUE, chipset < 0x10, GL_FALSE);
|
||||
assert(config);
|
||||
|
||||
configs = driConcatConfigs(configs, config);
|
||||
|
@@ -804,7 +804,7 @@ __DRIconfig **radeonInitScreen2(__DRIscreen *psp)
|
||||
ARRAY_SIZE(back_buffer_modes),
|
||||
msaa_samples_array,
|
||||
ARRAY_SIZE(msaa_samples_array),
|
||||
GL_TRUE, GL_FALSE);
|
||||
GL_TRUE, GL_FALSE, GL_FALSE);
|
||||
configs = driConcatConfigs(configs, new_configs);
|
||||
}
|
||||
|
||||
|
@@ -272,7 +272,7 @@ swrastFillInModes(__DRIscreen *psp,
|
||||
depth_bits_array, stencil_bits_array,
|
||||
depth_buffer_factor, back_buffer_modes,
|
||||
back_buffer_factor, msaa_samples_array, 1,
|
||||
GL_TRUE, GL_FALSE);
|
||||
GL_TRUE, GL_FALSE, GL_FALSE);
|
||||
if (configs == NULL) {
|
||||
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
|
||||
__LINE__);
|
||||
|
@@ -213,6 +213,9 @@ struct gl_config
|
||||
|
||||
/* EXT_framebuffer_sRGB */
|
||||
GLint sRGBCapable;
|
||||
|
||||
/* EGL_KHR_mutable_render_buffer */
|
||||
GLuint mutableRenderBuffer; /* bool */
|
||||
};
|
||||
|
||||
|
||||
|
@@ -656,9 +656,6 @@ st_context_flush(struct st_context_iface *stctxi, unsigned flags,
|
||||
st->pipe->screen->fence_reference(st->pipe->screen, fence, NULL);
|
||||
}
|
||||
|
||||
if (flags & ST_FLUSH_FRONT)
|
||||
st_manager_flush_frontbuffer(st);
|
||||
|
||||
/* DRI3 changes the framebuffer after SwapBuffers, but we need to invoke
|
||||
* st_manager_validate_framebuffers to notice that.
|
||||
*
|
||||
|
Reference in New Issue
Block a user