From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Zhigang Gong" Subject: Re: [PATCH] uxa/glamor: Enable the rest glamor rendering functions. Date: Wed, 14 Dec 2011 12:08:30 +0800 Message-ID: <0ef901ccba16$0adcc870$20965950$@linux.intel.com> References: <1323786701-29955-1-git-send-email-zhigang.gong@linux.intel.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0EFA_01CCBA59.19022B50" Return-path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id 355B09E7CE for ; Tue, 13 Dec 2011 20:08:34 -0800 (PST) In-Reply-To: Content-Language: zh-cn List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org To: 'Chris Wilson' Cc: intel-gfx@lists.freedesktop.org List-Id: intel-gfx@lists.freedesktop.org This is a multipart message in MIME format. ------=_NextPart_000_0EFA_01CCBA59.19022B50 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit > -----Original Message----- > From: Chris Wilson [mailto:chris@chris-wilson.co.uk] > Sent: Wednesday, December 14, 2011 2:45 AM > To: zhigang.gong@linux.intel.com > Cc: intel-gfx@lists.freedesktop.org; zhigang.gong@gmail.com; > zhigang.gong@linux.intel.com > Subject: Re: [PATCH] uxa/glamor: Enable the rest glamor rendering > functions. > > On Tue, 13 Dec 2011 22:31:41 +0800, zhigang.gong@linux.intel.com > wrote: > > From: Zhigang Gong > > > > This commit enable all the rest glamor rendering functions. > > Tested with latest glamor master branch, can pass rendercheck. > > Hmm, it exposes an issue with keeping a bo cache independent of mesa > and trying to feed it our own handles: > > Region for name 6 already exists but is not compatible > > The w/a for this would be: > > diff --git a/src/intel_glamor.c b/src/intel_glamor.c index 0cf8ed7..2757fd6 > 100644 > --- a/src/intel_glamor.c > +++ b/src/intel_glamor.c > @@ -91,6 +91,7 @@ intel_glamor_create_textured_pixmap(PixmapPtr > pixmap) > priv = intel_get_pixmap_private(pixmap); > if (glamor_egl_create_textured_pixmap(pixmap, > priv->bo->handle, > priv->stride)) { > + drm_intel_bo_disable_reuse(priv->bo); > priv->pinned = 1; > return TRUE; > } else > > but that gives up all pretense of maintaining a bo cache. Yes, I think this impacts the performance. Actually, I noticed this problem and I spent some time to track the root cause. If everything is ok, this error should not be triggered. Although the same BO maybe reused to create a new pixmap, the previous pixmap which own this BO should be already destroyed. And the previous image created with the previous pixmap should be destroyed either. And then, when we create a new pixmap/image with this BO, MESA should not find any exist image/region for this BO. But it does happen. I tracked further into mesa internal and found that the previous image was not destroyed when we call eglDestroyImageKHR, as its reference count is decreased to zero. It's weird for me. Further tracking shows that the root cause is when I use the texture(bind to the image) as a shader's source texture, and call glDrawArrays to perform the rendering, the texture's reference count will be increased by 1 before return from glDrawArrays. And I failed to find any API to decrease it. Then this texture can't be freed when destroy that texture and thus the image's reference count will also remain 1 and can't be freed either. The attached is a simple case to show this bug. It was modified from the eglkms.c in mesa-demos. I did send this issue to mesa-dev. Don't have a solution or explanation so far. Any idea? > -Chris > > -- > Chris Wilson, Intel Open Source Technology Centre ------=_NextPart_000_0EFA_01CCBA59.19022B50 Content-Type: application/octet-stream; name="eglkms_mod.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="eglkms_mod.c" #include =0A= #include =0A= =0A= #define EGL_EGLEXT_PROTOTYPES=0A= #define GL_GLEXT_PROTOTYPES=0A= =0A= #include =0A= #include =0A= #include =0A= =0A= #ifndef GLAPIENTRY=0A= #define GLAPIENTRY=0A= #endif=0A= =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= =0A= #ifdef GL_OES_EGL_image=0A= static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC = glEGLImageTargetTexture2DOES_func;=0A= static PFNEGLCREATEIMAGEKHRPROC glEGLCreateImageKHR_func; =0A= #endif=0A= =0A= static const char device_name[] =3D "/dev/dri/card0";=0A= GLint copy_prog;=0A= =0A= static GLint=0A= compile_glsl_prog(GLenum type, const char *source)=0A= {=0A= GLint ok;=0A= GLint prog;=0A= =0A= prog =3D glCreateShader(type);=0A= glShaderSource(prog, 1, (const GLchar **) &source, NULL);=0A= glCompileShader(prog);=0A= glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);=0A= if (!ok) {=0A= GLchar *info;=0A= GLint size;=0A= =0A= glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);=0A= info =3D malloc(size);=0A= glGetShaderInfoLog(prog, size, NULL, info);=0A= fprintf(stderr, "Failed to compile %s: %s\n",=0A= type =3D=3D GL_FRAGMENT_SHADER ? "FS" : "VS", info);=0A= fprintf(stderr, "Program source:\n%s", source);=0A= }=0A= =0A= return prog;=0A= }=0A= =0A= static void=0A= link_glsl_prog(GLint prog)=0A= {=0A= GLint ok;=0A= =0A= glLinkProgram(prog);=0A= glGetProgramiv(prog, GL_LINK_STATUS, &ok);=0A= if (!ok) {=0A= GLchar *info;=0A= GLint size;=0A= glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);=0A= info =3D malloc(size);=0A= glGetProgramInfoLog(prog, size, NULL, info);=0A= fprintf(stderr, "Failed to link: %s\n", info);=0A= fprintf(stderr, "GLSL link failure\n");=0A= }=0A= }=0A= =0A= #define VERTEX_POS 0=0A= #define VERTEX_SOURCE 1=0A= =0A= static void =0A= init_shader(void)=0A= {=0A= const char *copy_vs =3D=0A= "attribute vec4 v_position;\n"=0A= "attribute vec4 v_texcoord0;\n"=0A= "varying vec2 source_texture;\n"=0A= "void main()\n"=0A= "{\n"=0A= " gl_Position =3D v_position;\n"=0A= " source_texture =3D v_texcoord0.xy;\n" "}\n";=0A= =0A= const char *copy_fs =3D=0A= "varying vec2 source_texture;\n"=0A= "uniform sampler2D sampler;\n"=0A= "void main()\n"=0A= "{\n"=0A= " gl_FragColor =3D texture2D(sampler, source_texture).rgba;\n"=0A= " } \n" ;=0A= =0A= GLint sampler_uniform_location;=0A= GLint fs_prog, vs_prog;=0A= =0A= copy_prog =3D glCreateProgram();=0A= vs_prog =3D compile_glsl_prog(GL_VERTEX_SHADER, copy_vs);=0A= fs_prog =3D compile_glsl_prog(GL_FRAGMENT_SHADER, copy_fs);=0A= glAttachShader(copy_prog, vs_prog);=0A= glAttachShader(copy_prog, fs_prog);=0A= glBindAttribLocation(copy_prog, VERTEX_POS, "v_position");=0A= glBindAttribLocation(copy_prog, VERTEX_SOURCE, "v_texcoord0");=0A= link_glsl_prog(copy_prog);=0A= glUseProgram(copy_prog);=0A= sampler_uniform_location =3D glGetUniformLocation(copy_prog, = "sampler");=0A= glUniform1i(sampler_uniform_location, 0);=0A= glUseProgram(0);=0A= }=0A= =0A= static GLuint =0A= create_tex_from_img(EGLImageKHR image)=0A= {=0A= GLuint tex;=0A= =0A= glGenTextures(1, &tex);=0A= glBindTexture(GL_TEXTURE_2D, tex);=0A= glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);=0A= glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);=0A= glEGLImageTargetTexture2DOES_func (GL_TEXTURE_2D, image);=0A= glBindTexture(GL_TEXTURE_2D, 0);=0A= =0A= return tex;=0A= }=0A= =0A= static GLuint =0A= create_fbo_render2tex(GLint tex)=0A= {=0A= GLuint fb;=0A= =0A= glGenFramebuffers(1, &fb);=0A= glBindFramebuffer(GL_FRAMEBUFFER, fb);=0A= glFramebufferTexture2D(GL_FRAMEBUFFER,=0A= GL_COLOR_ATTACHMENT0,=0A= GL_TEXTURE_2D, tex,=0A= 0);=0A= =0A= if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) !=3D=0A= GL_FRAMEBUFFER_COMPLETE) {=0A= fprintf(stderr, "framebuffer not complete\n");=0A= exit(1);=0A= }=0A= =0A= return fb;=0A= }=0A= =0A= static EGLImageKHR =0A= create_image_from_handle(EGLDisplay dpy, EGLContext ctx, =0A= int fd, int handle, int width, =0A= int height, int stride, int bpp)=0A= {=0A= struct drm_gem_flink flink;=0A= EGLImageKHR image;=0A= EGLint attribs[] =3D {=0A= EGL_WIDTH, 0,=0A= EGL_HEIGHT, 0,=0A= EGL_DRM_BUFFER_STRIDE_MESA, 0,=0A= EGL_DRM_BUFFER_FORMAT_MESA,=0A= EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,=0A= EGL_DRM_BUFFER_USE_MESA,=0A= EGL_DRM_BUFFER_USE_SHARE_MESA,=0A= EGL_NONE=0A= };=0A= =0A= attribs[1] =3D width;=0A= attribs[3] =3D height;=0A= attribs[5] =3D stride * bpp/8;=0A= =0A= flink.handle =3D handle;=0A= if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0)=0A= return EGL_NO_IMAGE_KHR;=0A= =0A= image =3D glEGLCreateImageKHR_func(dpy , ctx,=0A= EGL_DRM_BUFFER_MESA,=0A= (void *) (uintptr_t)flink.name, attribs);=0A= if (image =3D=3D EGL_NO_IMAGE_KHR)=0A= return EGL_NO_IMAGE_KHR;=0A= =0A= return image;=0A= }=0A= =0A= /* use shader to copy tex to current fbo. */=0A= static void =0A= copy_tex(GLint tex)=0A= {=0A= static float vertices[8] =3D { -1, -1,=0A= 1, -1,=0A= 1, 1,=0A= -1, 1=0A= };=0A= static float texcoords[8] =3D { 0, 1,=0A= 1, 1,=0A= 1, 0,=0A= 0, 0=0A= };=0A= =0A= glVertexAttribPointer(VERTEX_POS, 2, GL_FLOAT,=0A= GL_FALSE, 2 * sizeof(float),=0A= vertices);=0A= glEnableVertexAttribArray(VERTEX_POS);=0A= glVertexAttribPointer(VERTEX_SOURCE, 2, GL_FLOAT,=0A= GL_FALSE, 2 * sizeof(float),=0A= texcoords);=0A= glEnableVertexAttribArray(VERTEX_SOURCE);=0A= =0A= glActiveTexture(GL_TEXTURE0);=0A= glBindTexture(GL_TEXTURE_2D, tex);=0A= =0A= glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,=0A= GL_NEAREST);=0A= glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,=0A= GL_NEAREST);=0A= =0A= glUseProgram(copy_prog);=0A= =0A= glDrawArrays(GL_TRIANGLE_FAN, 0, 4);=0A= =0A= glUseProgram(0);=0A= glDisableVertexAttribArray(VERTEX_SOURCE);=0A= glDisableVertexAttribArray(VERTEX_POS);=0A= }=0A= =0A= =0A= =0A= int main(int argc, char *argv[])=0A= {=0A= EGLDisplay dpy;=0A= EGLContext ctx;=0A= EGLImageKHR shadow_image, screen_image;=0A= EGLint major, minor;=0A= const char *ver, *extensions;=0A= uint32_t shadow_handle, shadow_stride;=0A= int ret, fd;=0A= struct gbm_device *gbm;=0A= struct gbm_bo *shadow_bo, *screen_bo;=0A= GLuint shadow_tex, screen_tex, screen_fb;=0A= =0A= fd =3D open(device_name, O_RDWR);=0A= if (fd < 0) {=0A= /* Probably permissions error */=0A= fprintf(stderr, "couldn't open %s, skipping\n", device_name);=0A= return -1;=0A= }=0A= =0A= gbm =3D gbm_create_device(fd);=0A= if (gbm =3D=3D NULL) {=0A= fprintf(stderr, "couldn't create gbm device\n");=0A= ret =3D -1;=0A= goto close_fd;=0A= }=0A= =0A= dpy =3D eglGetDisplay(gbm);=0A= if (dpy =3D=3D EGL_NO_DISPLAY) {=0A= fprintf(stderr, "eglGetDisplay() failed\n");=0A= ret =3D -1;=0A= goto destroy_gbm_device;=0A= }=0A= =0A= if (!eglInitialize(dpy, &major, &minor)) {=0A= printf("eglInitialize() failed\n");=0A= ret =3D -1;=0A= goto egl_terminate;=0A= }=0A= =0A= ver =3D eglQueryString(dpy, EGL_VERSION);=0A= printf("EGL_VERSION =3D %s\n", ver);=0A= =0A= extensions =3D eglQueryString(dpy, EGL_EXTENSIONS);=0A= =0A= if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) {=0A= printf("No support for EGL_KHR_surfaceless_opengl\n");=0A= ret =3D -1;=0A= goto egl_terminate;=0A= }=0A= =0A= eglBindAPI(EGL_OPENGL_API);=0A= ctx =3D eglCreateContext(dpy, NULL, EGL_NO_CONTEXT, NULL);=0A= if (ctx =3D=3D NULL) {=0A= fprintf(stderr, "failed to create context\n");=0A= ret =3D -1;=0A= goto egl_terminate;=0A= }=0A= =0A= if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx)) {=0A= fprintf(stderr, "failed to make context current\n");=0A= ret =3D -1;=0A= goto destroy_context;=0A= }=0A= =0A= init_shader();=0A= =0A= glEGLImageTargetTexture2DOES_func =3D =0A= (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)=0A= eglGetProcAddress("glEGLImageTargetTexture2DOES");=0A= =0A= glEGLCreateImageKHR_func =3D (PFNEGLCREATEIMAGEKHRPROC)=0A= eglGetProcAddress("eglCreateImageKHR");=0A= =0A= =0A= shadow_bo =3D gbm_bo_create(gbm, 1024, 768,=0A= GBM_BO_FORMAT_XRGB8888,=0A= GBM_BO_USE_RENDERING);=0A= =0A= screen_bo =3D gbm_bo_create(gbm, 1024, 768,=0A= GBM_BO_FORMAT_XRGB8888,=0A= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);=0A= if (screen_bo =3D=3D NULL) {=0A= fprintf(stderr, "failed to create gbm screen bo\n");=0A= ret =3D -1;=0A= goto unmake_current;=0A= }=0A= =0A= shadow_handle =3D gbm_bo_get_handle(shadow_bo).u32;=0A= shadow_stride =3D gbm_bo_get_pitch(shadow_bo);=0A= =0A= shadow_image =3D create_image_from_handle(dpy, ctx, fd, =0A= shadow_handle, =0A= 1024, =0A= 768, =0A= shadow_stride,=0A= 32); =0A= screen_image =3D eglCreateImageKHR(dpy, NULL, EGL_NATIVE_PIXMAP_KHR, = screen_bo, NULL);=0A= if (screen_image =3D=3D EGL_NO_IMAGE_KHR || shadow_image =3D=3D = EGL_NO_IMAGE_KHR) {=0A= fprintf(stderr, "failed to create egl image\n");=0A= ret =3D -1;=0A= goto destroy_gbm_bo;=0A= }=0A= =0A= shadow_tex =3D create_tex_from_img(shadow_image);=0A= screen_tex =3D create_tex_from_img(screen_image);=0A= =0A= screen_fb =3D create_fbo_render2tex(screen_tex);=0A= =0A= /* Copy shadow texture to screen texture by using shader. */=0A= glBindFramebuffer(GL_FRAMEBUFFER, screen_fb);=0A= copy_tex(shadow_tex); =0A= glFlush();=0A= =0A= glDeleteFramebuffers(1, &screen_fb);=0A= glDeleteTextures(1, &shadow_tex);=0A= glDeleteTextures(1, &screen_tex);=0A= eglDestroyImageKHR(dpy, shadow_image);=0A= eglDestroyImageKHR(dpy, screen_image);=0A= /* Now create a smaller image from the same handle. */=0A= shadow_image =3D create_image_from_handle(dpy, ctx, fd, =0A= shadow_handle, =0A= 1024 / 2 , =0A= 768 / 2 , =0A= shadow_stride/2,=0A= 32);=0A= if (shadow_image =3D=3D EGL_NO_IMAGE_KHR) {=0A= =0A= /* As we already destroyed the first shadow image which =0A= created from the same handle, we should be able to =0A= create a smaller image from the same handle again. =0A= This is true, if we don't call into=0A= =0A= copy_tex(shadow_tex);=0A= =0A= But if we call into copy_tex, then we fail here. =0A= You will get error message from the mesa side as below:=0A= "Region for name 1 already exists but is not compatible "=0A= copy_tex(shadow_tex) is a function to use shadow =0A= texture as a texture source, and access it in a =0A= shader program to render the screen fbo. I traced=0A= into the code, and found that glDrawArray will =0A= implicitly increase the shadow texture's reference count.=0A= And then latter when we delete the texture, the =0A= count will remain 1 rather then zero, and then=0A= it will not decrease the corresponding image region's=0A= reference counter and then when we destroy the shadow image,=0A= the image's reference counter will also be 1 and can't=0A= be freed. Then next time we use the same handle to=0A= create a new image, it will find the previou zombie=0A= image region and find they are not compatible.=0A= =0A= simply comment out the glDrawArray can avoid the function=0A= goes here too. Don't know how to fix this problem.=0A= */=0A= fprintf(stderr, "hit a bug?\n");=0A= } else=0A= eglDestroyImageKHR(dpy, shadow_image);=0A= =0A= destroy_gbm_bo:=0A= gbm_bo_destroy(shadow_bo);=0A= gbm_bo_destroy(screen_bo);=0A= unmake_current:=0A= eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);=0A= destroy_context:=0A= eglDestroyContext(dpy, ctx);=0A= egl_terminate:=0A= eglTerminate(dpy);=0A= destroy_gbm_device:=0A= gbm_device_destroy(gbm);=0A= close_fd:=0A= close(fd);=0A= =0A= return ret;=0A= }=0A= ------=_NextPart_000_0EFA_01CCBA59.19022B50 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ------=_NextPart_000_0EFA_01CCBA59.19022B50--