Compare commits
	
		
			20 Commits
		
	
	
		
			mesa-20.0.
			...
			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