Пример #1
0
/**
 * Reference a framebuffer.
 */
static void
st_framebuffer_reference(struct st_framebuffer **ptr,
                         struct st_framebuffer *stfb)
{
   struct gl_framebuffer *fb = &stfb->Base;
   _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb);
}
Пример #2
0
static void
intelDestroyBuffer(__DRIdrawable * driDrawPriv)
{
    struct gl_framebuffer *fb = driDrawPriv->driverPrivate;
  
    _mesa_reference_framebuffer(&fb, NULL);
}
Пример #3
0
Файл: xm_api.c Проект: RAOF/mesa
/**
 * Remove buffer from linked list, delete if no longer referenced.
 */
static void
xmesa_free_buffer(XMesaBuffer buffer)
{
   XMesaBuffer prev = NULL, b;

   for (b = XMesaBufferList; b; b = b->Next) {
      if (b == buffer) {
         struct gl_framebuffer *fb = &buffer->mesa_buffer;

         /* unlink buffer from list */
         if (prev)
            prev->Next = buffer->Next;
         else
            XMesaBufferList = buffer->Next;

         /* mark as delete pending */
         fb->DeletePending = GL_TRUE;

         /* Since the X window for the XMesaBuffer is going away, we don't
          * want to dereference this pointer in the future.
          */
         b->frontxrb->drawable = 0;

         /* Unreference.  If count = zero we'll really delete the buffer */
         _mesa_reference_framebuffer(&fb, NULL);

         return;
      }
      /* continue search */
      prev = b;
   }
   /* buffer not found in XMesaBufferList */
   _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
}
Пример #4
0
void
radeonDestroyBuffer(__DRIdrawable *driDrawPriv)
{
    struct radeon_framebuffer *rfb;
    if (!driDrawPriv)
	return;

    rfb = (void*)driDrawPriv->driverPrivate;
    if (!rfb)
	return;
    radeon_cleanup_renderbuffers(rfb);
    _mesa_reference_framebuffer((struct gl_framebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
}
Пример #5
0
void
_mesa_meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
                                        struct gen_mipmap_state *mipmap)
{
   if (mipmap->VAO == 0)
      return;
   _mesa_DeleteVertexArrays(1, &mipmap->VAO);
   mipmap->VAO = 0;
   _mesa_reference_buffer_object(ctx, &mipmap->buf_obj, NULL);
   _mesa_reference_sampler_object(ctx, &mipmap->samp_obj, NULL);
   _mesa_reference_framebuffer(&mipmap->fb, NULL);

   _mesa_meta_blit_shader_table_cleanup(ctx, &mipmap->shaders);
}
Пример #6
0
void
glFBDevDestroyBuffer( GLFBDevBufferPtr buffer )
{
   if (buffer) {
      /* check if destroying the current buffer */
      GLFBDevBufferPtr curDraw = glFBDevGetCurrentDrawBuffer();
      GLFBDevBufferPtr curRead = glFBDevGetCurrentReadBuffer();
      if (buffer == curDraw || buffer == curRead) {
         glFBDevMakeCurrent( NULL, NULL, NULL);
      }
      {
         struct gl_framebuffer *fb = &buffer->glframebuffer;
         _mesa_reference_framebuffer(&fb, NULL);
      }
   }
}
Пример #7
0
static void
dri_destroy_buffer(__DRIdrawable * dPriv)
{
    TRACE;

    if (dPriv) {
	struct dri_drawable *drawable = dri_drawable(dPriv);
	struct gl_framebuffer *fb;

	free(drawable->row);

	fb = &drawable->Base;

	fb->DeletePending = GL_TRUE;
	_mesa_reference_framebuffer(&fb, NULL);
    }
}
Пример #8
0
/**
 * Destroy an Off-Screen Mesa rendering context.
 *
 * \param osmesa  the context to destroy
 */
GLAPI void GLAPIENTRY
OSMesaDestroyContext( OSMesaContext osmesa )
{
   if (osmesa) {
      if (osmesa->srb)
         _mesa_reference_renderbuffer((struct gl_renderbuffer **) &osmesa->srb, NULL);

      _mesa_meta_free( &osmesa->mesa );

      _swsetup_DestroyContext( &osmesa->mesa );
      _tnl_DestroyContext( &osmesa->mesa );
      _vbo_DestroyContext( &osmesa->mesa );
      _swrast_DestroyContext( &osmesa->mesa );

      _mesa_destroy_visual( osmesa->gl_visual );
      _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );

      _mesa_free_context_data( &osmesa->mesa );
      free( osmesa );
   }
}
Пример #9
0
/**
 * Free the data associated with the given context.
 * 
 * But doesn't free the GLcontext struct itself.
 *
 * \sa _mesa_initialize_context() and init_attrib_groups().
 */
void
_mesa_free_context_data( GLcontext *ctx )
{
   GLint RefCount;

   if (!_mesa_get_current_context()){
      /* No current context, but we may need one in order to delete
       * texture objs, etc.  So temporarily bind the context now.
       */
      _mesa_make_current(ctx, NULL, NULL);
   }

   /* unreference WinSysDraw/Read buffers */
   _mesa_reference_framebuffer(&ctx->WinSysDrawBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->WinSysReadBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->DrawBuffer, NULL);
   _mesa_reference_framebuffer(&ctx->ReadBuffer, NULL);

   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);

   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);

   _mesa_free_attrib_data(ctx);
   _mesa_free_lighting_data( ctx );
   _mesa_free_eval_data( ctx );
   _mesa_free_texture_data( ctx );
   _mesa_free_matrix_data( ctx );
   _mesa_free_viewport_data( ctx );
   _mesa_free_colortables_data( ctx );
   _mesa_free_program_data(ctx);
   _mesa_free_shader_state(ctx);
   _mesa_free_queryobj_data(ctx);
#if FEATURE_ARB_sync
   _mesa_free_sync_data(ctx);
#endif
   _mesa_free_varray_data(ctx);

   _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);

#if FEATURE_ARB_pixel_buffer_object
   _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
   _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
#endif

#if FEATURE_ARB_vertex_buffer_object
   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
   _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
#endif

   /* free dispatch tables */
   _mesa_free(ctx->Exec);
   _mesa_free(ctx->Save);

   /* Shared context state (display lists, textures, etc) */
   _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
   RefCount = --ctx->Shared->RefCount;
   _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
   assert(RefCount >= 0);
   if (RefCount == 0) {
      /* free shared state */
      _mesa_free_shared_state( ctx, ctx->Shared );
   }

   /* needs to be after freeing shared state */
   _mesa_free_display_list_data(ctx);

   if (ctx->Extensions.String)
      _mesa_free((void *) ctx->Extensions.String);

   /* unbind the context if it's currently bound */
   if (ctx == _mesa_get_current_context()) {
      _mesa_make_current(NULL, NULL, NULL);
   }
}
Пример #10
0
/**
 * Bind the given context to the given drawBuffer and readBuffer and
 * make it the current context for the calling thread.
 * We'll render into the drawBuffer and read pixels from the
 * readBuffer (i.e. glRead/CopyPixels, glCopyTexImage, etc).
 *
 * We check that the context's and framebuffer's visuals are compatible
 * and return immediately if they're not.
 *
 * \param newCtx  the new GL context. If NULL then there will be no current GL
 *                context.
 * \param drawBuffer  the drawing framebuffer
 * \param readBuffer  the reading framebuffer
 */
GLboolean
_mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
                    GLframebuffer *readBuffer )
{
   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(newCtx, "_mesa_make_current()\n");

   /* Check that the context's and framebuffer's visuals are compatible.
    */
   if (newCtx && drawBuffer && newCtx->WinSysDrawBuffer != drawBuffer) {
      if (!check_compatible(newCtx, drawBuffer)) {
         _mesa_warning(newCtx,
              "MakeCurrent: incompatible visuals for context and drawbuffer");
         return GL_FALSE;
      }
   }
   if (newCtx && readBuffer && newCtx->WinSysReadBuffer != readBuffer) {
      if (!check_compatible(newCtx, readBuffer)) {
         _mesa_warning(newCtx,
              "MakeCurrent: incompatible visuals for context and readbuffer");
         return GL_FALSE;
      }
   }

   /* We used to call _glapi_check_multithread() here.  Now do it in drivers */
   _glapi_set_context((void *) newCtx);
   ASSERT(_mesa_get_current_context() == newCtx);

   if (!newCtx) {
      _glapi_set_dispatch(NULL);  /* none current */
   }
   else {
      _glapi_set_dispatch(newCtx->CurrentDispatch);

      if (drawBuffer && readBuffer) {
	 /* TODO: check if newCtx and buffer's visual match??? */

         ASSERT(drawBuffer->Name == 0);
         ASSERT(readBuffer->Name == 0);
         _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer);
         _mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer);

         /*
          * Only set the context's Draw/ReadBuffer fields if they're NULL
          * or not bound to a user-created FBO.
          */
         if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
            /* KW: merge conflict here, revisit. 
             */
            /* fix up the fb fields - these will end up wrong otherwise
             * if the DRIdrawable changes, and everything relies on them.
             * This is a bit messy (same as needed in _mesa_BindFramebufferEXT)
             */
            unsigned int i;
            GLenum buffers[MAX_DRAW_BUFFERS];

            _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer);

            for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) {
               buffers[i] = newCtx->Color.DrawBuffer[i];
            }

            _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL);
         }
         if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
            _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
         }

         /* XXX only set this flag if we're really changing the draw/read
          * framebuffer bindings.
          */
	 newCtx->NewState |= _NEW_BUFFERS;

#if 1
         /* We want to get rid of these lines: */

#if _HAVE_FULL_GL
         if (!drawBuffer->Initialized) {
            initialize_framebuffer_size(newCtx, drawBuffer);
         }
         if (readBuffer != drawBuffer && !readBuffer->Initialized) {
            initialize_framebuffer_size(newCtx, readBuffer);
         }

	 _mesa_resizebuffers(newCtx);
#endif

#else
         /* We want the drawBuffer and readBuffer to be initialized by
          * the driver.
          * This generally means the Width and Height match the actual
          * window size and the renderbuffers (both hardware and software
          * based) are allocated to match.  The later can generally be
          * done with a call to _mesa_resize_framebuffer().
          *
          * It's theoretically possible for a buffer to have zero width
          * or height, but for now, assert check that the driver did what's
          * expected of it.
          */
         ASSERT(drawBuffer->Width > 0);
         ASSERT(drawBuffer->Height > 0);
#endif

         if (drawBuffer) {
            _mesa_check_init_viewport(newCtx,
                                      drawBuffer->Width, drawBuffer->Height);
         }
      }

      if (newCtx->FirstTimeCurrent) {
         check_context_limits(newCtx);

         /* We can use this to help debug user's problems.  Tell them to set
          * the MESA_INFO env variable before running their app.  Then the
          * first time each context is made current we'll print some useful
          * information.
          */
	 if (_mesa_getenv("MESA_INFO")) {
	    _mesa_print_info();
	 }

	 newCtx->FirstTimeCurrent = GL_FALSE;
      }
   }
   
   return GL_TRUE;
}
Пример #11
0
static void
nouveau_destroy_buffer(__DRIdrawable *drawable)
{
	_mesa_reference_framebuffer(
		(struct gl_framebuffer **)&drawable->driverPrivate, NULL);
}
Пример #12
0
/** A partial implementation of glCopyImageSubData
 *
 * This is a partial implementation of glCopyImageSubData that works only
 * if both textures are uncompressed and the destination texture is
 * renderable.  It uses a slight abuse of a texture view (see make_view) to
 * turn the source texture into the destination texture type and then uses
 * _mesa_meta_BlitFramebuffers to do the copy.
 */
bool
_mesa_meta_CopyImageSubData_uncompressed(struct gl_context *ctx,
                                         struct gl_texture_image *src_tex_image,
                                         struct gl_renderbuffer *src_renderbuffer,
                                         int src_x, int src_y, int src_z,
                                         struct gl_texture_image *dst_tex_image,
                                         struct gl_renderbuffer *dst_renderbuffer,
                                         int dst_x, int dst_y, int dst_z,
                                         int src_width, int src_height)
{
   mesa_format src_format, dst_format;
   GLint src_internal_format, dst_internal_format;
   GLuint src_view_texture = 0;
   struct gl_texture_image *src_view_tex_image;
   struct gl_framebuffer *readFb;
   struct gl_framebuffer *drawFb = NULL;
   bool success = false;
   GLbitfield mask;
   GLenum status, attachment;

   if (src_renderbuffer) {
      src_format = src_renderbuffer->Format;
      src_internal_format = src_renderbuffer->InternalFormat;
   } else {
      assert(src_tex_image);
      src_format = src_tex_image->TexFormat;
      src_internal_format = src_tex_image->InternalFormat;
   }

   if (dst_renderbuffer) {
      dst_format = dst_renderbuffer->Format;
      dst_internal_format = dst_renderbuffer->InternalFormat;
   } else {
      assert(dst_tex_image);
      dst_format = dst_tex_image->TexFormat;
      dst_internal_format = dst_tex_image->InternalFormat;
   }

   if (_mesa_is_format_compressed(src_format))
      return false;

   if (_mesa_is_format_compressed(dst_format))
      return false;

   if (src_internal_format == dst_internal_format) {
      src_view_tex_image = src_tex_image;
   } else {
      if (src_renderbuffer) {
         assert(src_tex_image == NULL);
         src_tex_image = wrap_renderbuffer(ctx, src_renderbuffer);
      }
      if (!make_view(ctx, src_tex_image, &src_view_tex_image, &src_view_texture,
                     dst_internal_format))
         goto cleanup;
   }

   /* We really only need to stash the bound framebuffers and scissor. */
   _mesa_meta_begin(ctx, MESA_META_SCISSOR);

   readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (readFb == NULL)
      goto meta_end;

   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (drawFb == NULL)
      goto meta_end;

   _mesa_bind_framebuffers(ctx, drawFb, readFb);

   switch (_mesa_get_format_base_format(src_format)) {
   case GL_DEPTH_COMPONENT:
      attachment = GL_DEPTH_ATTACHMENT;
      mask = GL_DEPTH_BUFFER_BIT;
      break;
   case GL_DEPTH_STENCIL:
      attachment = GL_DEPTH_STENCIL_ATTACHMENT;
      mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
      break;
   case GL_STENCIL_INDEX:
      attachment = GL_STENCIL_ATTACHMENT;
      mask = GL_STENCIL_BUFFER_BIT;
      break;
   default:
      attachment = GL_COLOR_ATTACHMENT0;
      mask = GL_COLOR_BUFFER_BIT;
      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);
      _mesa_ReadBuffer(GL_COLOR_ATTACHMENT0);
   }

   if (src_view_tex_image) {
      /* Prefer the tex image because, even if we have a renderbuffer, we may
       * have had to wrap it in a texture view.
       */
      _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, attachment,
                                           src_view_tex_image, src_z);
   } else {
      _mesa_framebuffer_renderbuffer(ctx, ctx->ReadBuffer, attachment,
                                     src_renderbuffer);
   }

   status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto meta_end;

   if (dst_renderbuffer) {
      _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, attachment,
                                     dst_renderbuffer);
   } else {
      _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, attachment,
                                           dst_tex_image, dst_z);
   }

   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto meta_end;

   /* Explicitly disable sRGB encoding */
   ctx->DrawBuffer->Visual.sRGBCapable = false;

   /* Since we've bound a new draw framebuffer, we need to update its
    * derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to
    * be correct.
    */
   _mesa_update_state(ctx);

   /* We skip the core BlitFramebuffer checks for format consistency.
    * We have already created views to ensure that the texture formats
    * match.
    */
   ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                               src_x, src_y,
                               src_x + src_width, src_y + src_height,
                               dst_x, dst_y,
                               dst_x + src_width, dst_y + src_height,
                               mask, GL_NEAREST);

   success = true;

meta_end:
   _mesa_reference_framebuffer(&readFb, NULL);
   _mesa_reference_framebuffer(&drawFb, NULL);
   _mesa_meta_end(ctx);

cleanup:
   _mesa_DeleteTextures(1, &src_view_texture);

   /* If we got a renderbuffer source, delete the temporary texture */
   if (src_renderbuffer && src_tex_image)
      ctx->Driver.DeleteTexture(ctx, src_tex_image->TexObject);

   return success;
}
Пример #13
0
void GLAPIENTRY
_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
{
   struct gl_framebuffer *newFb, *newFbread;
   GLboolean bindReadBuf, bindDrawBuf;
   GET_CURRENT_CONTEXT(ctx);

   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (!ctx->Extensions.EXT_framebuffer_object) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glBindFramebufferEXT(unsupported)");
      return;
   }

   switch (target) {
#if FEATURE_EXT_framebuffer_blit
   case GL_DRAW_FRAMEBUFFER_EXT:
      if (!ctx->Extensions.EXT_framebuffer_blit) {
         _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
         return;
      }
      bindDrawBuf = GL_TRUE;
      bindReadBuf = GL_FALSE;
      break;
   case GL_READ_FRAMEBUFFER_EXT:
      if (!ctx->Extensions.EXT_framebuffer_blit) {
         _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
         return;
      }
      bindDrawBuf = GL_FALSE;
      bindReadBuf = GL_TRUE;
      break;
#endif
   case GL_FRAMEBUFFER_EXT:
      bindDrawBuf = GL_TRUE;
      bindReadBuf = GL_TRUE;
      break;
   default:
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
      return;
   }

   FLUSH_VERTICES(ctx, _NEW_BUFFERS);

   if (ctx->Driver.Flush) {  
      ctx->Driver.Flush(ctx);
   }

   if (framebuffer) {
      /* Binding a user-created framebuffer object */
      newFb = _mesa_lookup_framebuffer(ctx, framebuffer);
      if (newFb == &DummyFramebuffer) {
         /* ID was reserved, but no real framebuffer object made yet */
         newFb = NULL;
      }
      if (!newFb) {
	 /* create new framebuffer object */
	 newFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
	 if (!newFb) {
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
	    return;
	 }
         _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb);
      }
      newFbread = newFb;
   }
   else {
      /* Binding the window system framebuffer (which was originally set
       * with MakeCurrent).
       */
      newFb = ctx->WinSysDrawBuffer;
      newFbread = ctx->WinSysReadBuffer;
   }

   ASSERT(newFb);
   ASSERT(newFb != &DummyFramebuffer);

   /*
    * XXX check if re-binding same buffer and skip some of this code.
    */

   if (bindReadBuf) {
      _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread);
   }

   if (bindDrawBuf) {
      /* check if old FB had any texture attachments */
      check_end_texture_render(ctx, ctx->DrawBuffer);

      /* check if time to delete this framebuffer */
      _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb);

      if (newFb->Name != 0) {
         /* check if newly bound framebuffer has any texture attachments */
         check_begin_texture_render(ctx, newFb);
      }
   }

   if (ctx->Driver.BindFramebuffer) {
      ctx->Driver.BindFramebuffer(ctx, target, newFb, newFbread);
   }
}
Пример #14
0
bool
_mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims,
                              struct gl_texture_image *tex_image,
                              int xoffset, int yoffset, int zoffset,
                              int width, int height, int depth,
                              GLenum format, GLenum type, const void *pixels,
                              const struct gl_pixelstore_attrib *packing)
{
   struct gl_buffer_object *pbo = NULL;
   GLuint pbo_tex = 0;
   struct gl_framebuffer *readFb;
   struct gl_framebuffer *drawFb;
   int image_height;
   struct gl_texture_image *pbo_tex_image;
   struct gl_renderbuffer *rb = NULL;
   GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
   GLenum status, src_base_format;
   bool success = false, clear_channels_to_zero = false;
   float save_clear_color[4];
   int z;

   if (!_mesa_is_bufferobj(packing->BufferObj))
      return false;

   if (format == GL_DEPTH_COMPONENT ||
       format == GL_DEPTH_STENCIL ||
       format == GL_STENCIL_INDEX ||
       format == GL_COLOR_INDEX)
      return false;

   /* Don't use meta path for readpixels in below conditions. */
   if (!tex_image) {
      rb = ctx->ReadBuffer->_ColorReadBuffer;

      /* _mesa_get_readpixels_transfer_ops() includes the cases of read
       * color clamping along with the ctx->_ImageTransferState.
       */
      if (_mesa_get_readpixels_transfer_ops(ctx, rb->Format, format,
                                            type, GL_FALSE))
         return false;

      if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat,
                                                 dstBaseFormat))
         return false;

      /* This function rely on BlitFramebuffer to fill in the pixel data for
       * ReadPixels. But, BlitFrameBuffer doesn't support signed to unsigned
       * or unsigned to signed integer conversions. OpenGL spec expects an
       * invalid operation in that case.
       */
      if (need_signed_unsigned_int_conversion(rb->Format, format, type))
         return false;
   } else {
      if (need_signed_unsigned_int_conversion(tex_image->TexFormat, format, type))
         return false;
   }

   /* For arrays, use a tall (height * depth) 2D texture but taking into
    * account the inter-image padding specified with the image height packing
    * property.
    */
   image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight;

   _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER |
                           MESA_META_PIXEL_STORE));

   pbo_tex_image = create_texture_for_pbo(ctx, false, GL_PIXEL_PACK_BUFFER,
                                          dims, width, height, depth,
                                          format, type, pixels, packing,
                                          &pbo, &pbo_tex);

   if (!pbo_tex_image) {
      _mesa_meta_end(ctx);
      return false;
   }

   /* GL_CLAMP_FRAGMENT_COLOR doesn't affect ReadPixels and GettexImage */
   if (ctx->Extensions.ARB_color_buffer_float)
      _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);

   readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (readFb == NULL)
      goto fail;

   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (drawFb == NULL)
      goto fail;

   if (tex_image && tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      assert(depth == 1);
      assert(zoffset == 0);
      depth = height;
      height = 1;
      image_height = 1;
      zoffset = yoffset;
      yoffset = 0;
   }

   /* If we were given a texture, bind it to the read framebuffer.  If not,
    * we're doing a ReadPixels and we should just use whatever framebuffer
    * the client has bound.
    */
   _mesa_bind_framebuffers(ctx, drawFb, tex_image ? readFb : ctx->ReadBuffer);
   if (tex_image) {
      _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer,
                                           GL_COLOR_ATTACHMENT0,
                                           tex_image, zoffset);
      /* If this passes on the first layer it should pass on the others */
      status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer);
      if (status != GL_FRAMEBUFFER_COMPLETE)
         goto fail;
   } else {
      assert(depth == 1);
   }

   _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
                                        GL_COLOR_ATTACHMENT0,
                                        pbo_tex_image, 0);
   /* If this passes on the first layer it should pass on the others */
   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto fail;

   /* Explicitly disable sRGB encoding */
   ctx->DrawBuffer->Visual.sRGBCapable = false;

   _mesa_update_state(ctx);

   if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                                  xoffset, yoffset,
                                  xoffset + width, yoffset + height,
                                  0, 0, width, height,
                                  GL_COLOR_BUFFER_BIT, GL_NEAREST))
      goto fail;

   src_base_format = tex_image ?
                     tex_image->_BaseFormat :
                     ctx->ReadBuffer->_ColorReadBuffer->_BaseFormat;

   /* Depending on the base formats involved we might need to rebase some
    * values. For example if we download from a Luminance format to RGBA
    * format, we want G=0 and B=0.
    */
   clear_channels_to_zero =
      _mesa_need_luminance_to_rgb_conversion(src_base_format,
                                             pbo_tex_image->_BaseFormat);

   if (clear_channels_to_zero) {
      memcpy(save_clear_color, ctx->Color.ClearColor.f, 4 * sizeof(float));
      /* Clear the Green, Blue channels. */
      _mesa_ColorMask(GL_FALSE, GL_TRUE, GL_TRUE,
                      src_base_format != GL_LUMINANCE_ALPHA);
      _mesa_ClearColor(0.0, 0.0, 0.0, 1.0);
      _mesa_Clear(GL_COLOR_BUFFER_BIT);
   }

   for (z = 1; z < depth; z++) {
      _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer,
                                           GL_COLOR_ATTACHMENT0,
                                           tex_image, zoffset + z);

      _mesa_update_state(ctx);

      _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                                 xoffset, yoffset,
                                 xoffset + width, yoffset + height,
                                 0, z * image_height,
                                 width, z * image_height + height,
                                 GL_COLOR_BUFFER_BIT, GL_NEAREST);
      if (clear_channels_to_zero)
         _mesa_Clear(GL_COLOR_BUFFER_BIT);
   }

   /* Unmask the color channels and restore the saved clear color values. */
   if (clear_channels_to_zero) {
      _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      _mesa_ClearColor(save_clear_color[0], save_clear_color[1],
                       save_clear_color[2], save_clear_color[3]);
   }

   success = true;

fail:
   _mesa_reference_framebuffer(&drawFb, NULL);
   _mesa_reference_framebuffer(&readFb, NULL);
   _mesa_DeleteTextures(1, &pbo_tex);
   _mesa_reference_buffer_object(ctx, &pbo, NULL);

   _mesa_meta_end(ctx);

   return success;
}
Пример #15
0
bool
_mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims,
                           struct gl_texture_image *tex_image,
                           int xoffset, int yoffset, int zoffset,
                           int width, int height, int depth,
                           GLenum format, GLenum type, const void *pixels,
                           bool create_pbo,
                           const struct gl_pixelstore_attrib *packing)
{
   struct gl_buffer_object *pbo = NULL;
   GLuint pbo_tex = 0;
   struct gl_framebuffer *readFb = NULL;
   struct gl_framebuffer *drawFb = NULL;
   int image_height;
   struct gl_texture_image *pbo_tex_image;
   GLenum status;
   bool success = false;
   int z;

   if (!_mesa_is_bufferobj(packing->BufferObj) &&
       (!create_pbo || pixels == NULL))
      return false;

   if (format == GL_DEPTH_COMPONENT ||
       format == GL_DEPTH_STENCIL ||
       format == GL_STENCIL_INDEX ||
       format == GL_COLOR_INDEX)
      return false;

   if (ctx->_ImageTransferState)
      return false;

   /* This function rely on BlitFramebuffer to fill in the pixel data for
    * glTex[Sub]Image*D. But, BlitFrameBuffer doesn't support signed to
    * unsigned or unsigned to signed integer conversions.
    */
   if (need_signed_unsigned_int_conversion(tex_image->TexFormat, format, type))
      return false;

   /* For arrays, use a tall (height * depth) 2D texture but taking into
    * account the inter-image padding specified with the image height packing
    * property.
    */
   image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight;

   _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER |
                           MESA_META_PIXEL_STORE));

   pbo_tex_image = create_texture_for_pbo(ctx, create_pbo,
                                          GL_PIXEL_UNPACK_BUFFER,
                                          dims, width, height, depth,
                                          format, type, pixels, packing,
                                          &pbo, &pbo_tex);
   if (!pbo_tex_image) {
      _mesa_meta_end(ctx);
      return false;
   }

   readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (readFb == NULL)
      goto fail;

   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (drawFb == NULL)
      goto fail;

   _mesa_bind_framebuffers(ctx, drawFb, tex_image ? readFb : ctx->ReadBuffer);

   if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      assert(depth == 1);
      assert(zoffset == 0);
      depth = height;
      height = 1;
      image_height = 1;
      zoffset = yoffset;
      yoffset = 0;
   }

   _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer,
                                        GL_COLOR_ATTACHMENT0,
                                        pbo_tex_image, 0);
   /* If this passes on the first layer it should pass on the others */
   status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto fail;

   _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
                                        GL_COLOR_ATTACHMENT0,
                                        tex_image, zoffset);
   /* If this passes on the first layer it should pass on the others */
   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto fail;

   /* Explicitly disable sRGB encoding */
   ctx->DrawBuffer->Visual.sRGBCapable = false;

   _mesa_update_state(ctx);

   if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                                  0, 0, width, height,
                                  xoffset, yoffset,
                                  xoffset + width, yoffset + height,
                                  GL_COLOR_BUFFER_BIT, GL_NEAREST))
      goto fail;

   for (z = 1; z < depth; z++) {
      _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer,
                                           GL_COLOR_ATTACHMENT0,
                                           tex_image, zoffset + z);

      _mesa_update_state(ctx);

      _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                                 0, z * image_height,
                                 width, z * image_height + height,
                                 xoffset, yoffset,
                                 xoffset + width, yoffset + height,
                                 GL_COLOR_BUFFER_BIT, GL_NEAREST);
   }

   success = true;

fail:
   _mesa_reference_framebuffer(&readFb, NULL);
   _mesa_reference_framebuffer(&drawFb, NULL);
   _mesa_DeleteTextures(1, &pbo_tex);
   _mesa_reference_buffer_object(ctx, &pbo, NULL);

   _mesa_meta_end(ctx);

   return success;
}
Пример #16
0
void
brw_meta_resolve_color(struct brw_context *brw,
                       struct intel_mipmap_tree *mt)
{
   struct gl_context *ctx = &brw->ctx;
   struct gl_framebuffer *drawFb;
   struct gl_renderbuffer *rb;
   struct rect rect;

   brw_emit_mi_flush(brw);

   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (drawFb == NULL) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "in %s", __func__);
      return;
   }

   _mesa_meta_begin(ctx, MESA_META_ALL);

   rb = brw_get_rb_for_slice(brw, mt, 0, 0, false);

   _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer);
   _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0,
                                  rb);
   _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);

   brw_fast_clear_init(brw);

   use_rectlist(brw, true);

   brw_bind_rep_write_shader(brw, (float *) fast_clear_color);

   /* SKL+ also has a resolve mode for compressed render targets and thus more
    * bits to let us select the type of resolve.  For fast clear resolves, it
    * turns out we can use the same value as pre-SKL though.
    */
   if (intel_miptree_is_lossless_compressed(brw, mt))
      set_fast_clear_op(brw, GEN9_PS_RENDER_TARGET_RESOLVE_FULL);
   else
      set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE);

   mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
   get_resolve_rect(brw, mt, &rect);

   brw_draw_rectlist(brw, &rect, 1);

   set_fast_clear_op(brw, 0);
   use_rectlist(brw, false);

   _mesa_reference_renderbuffer(&rb, NULL);
   _mesa_reference_framebuffer(&drawFb, NULL);

   _mesa_meta_end(ctx);

   /* We're typically called from intel_update_state() and we're supposed to
    * return with the state all updated to what it was before
    * brw_meta_resolve_color() was called.  The meta rendering will have
    * messed up the state and we need to call _mesa_update_state() again to
    * get back to where we were supposed to be when resolve was called.
    */
   if (ctx->NewState)
      _mesa_update_state(ctx);
}