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