Example #1
0
/**
 * Determine if we need to clear the stencil buffer by drawing a quad.
 */
static INLINE GLboolean
check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
                              boolean ds_separate)
{
   const struct st_renderbuffer *strb = st_renderbuffer(rb);
   const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
   const GLuint stencilMax = 0xff;
   const GLboolean maskStencil
      = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;

   assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);

   if (maskStencil) 
      return GL_TRUE;

   if (ctx->Scissor.Enabled &&
       (ctx->Scissor.X != 0 ||
        ctx->Scissor.Y != 0 ||
        ctx->Scissor.Width < rb->Width ||
        ctx->Scissor.Height < rb->Height))
      return GL_TRUE;

   /* This is correct, but it is necessary to look at the depth clear
    * value held in the surface when it comes time to issue the clear,
    * rather than taking depth and stencil clear values from the
    * current state.
    */
   if (!ds_separate && isDS && ctx->DrawBuffer->Visual.depthBits > 0)
      return GL_TRUE;

   return GL_FALSE;
}
static void
st_egl_image_target_renderbuffer_storage(struct gl_context *ctx,
					 struct gl_renderbuffer *rb,
					 GLeglImageOES image_handle)
{
   struct st_context *st = st_context(ctx);
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_surface *ps;
   unsigned usage;

   usage = PIPE_BIND_RENDER_TARGET;
   ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage);
   if (ps) {
      strb->Base.Width = ps->width;
      strb->Base.Height = ps->height;
      strb->Base.Format = st_pipe_format_to_mesa_format(ps->format);
      strb->Base.DataType = st_format_datatype(ps->format);
      strb->Base._BaseFormat = st_pipe_format_to_base_format(ps->format);
      strb->Base.InternalFormat = strb->Base._BaseFormat;

      pipe_surface_reference(&strb->surface, ps);
      pipe_resource_reference(&strb->texture, ps->texture);

      pipe_surface_reference(&ps, NULL);
   }
}
Example #3
0
/** Undo surface-to-texture binding */
int
st_release_teximage(struct st_framebuffer *stfb, uint surfIndex,
                    int target, int format, int level)
{
   GET_CURRENT_CONTEXT(ctx);
   struct st_context *st = ctx->st;
   struct st_renderbuffer *strb;

   assert(surfIndex <= ST_SURFACE_DEPTH);

   strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);

   if (!strb->texture_save || !strb->surface_save) {
      /* Error! */
      return 0;
   }

   st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);

   /* free tex surface, restore original */
   pipe_surface_reference(&strb->surface, strb->surface_save);
   pipe_texture_reference(&strb->texture, strb->texture_save);

   pipe_surface_reference(&strb->surface_save, NULL);
   pipe_texture_reference(&strb->texture_save, NULL);

   st->dirty.st |= ST_NEW_FRAMEBUFFER;

   return 1;
}
Example #4
0
/**
 * Determine if we need to clear the stencil buffer by drawing a quad.
 */
static INLINE GLboolean
check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
{
   const struct st_renderbuffer *strb = st_renderbuffer(rb);
   const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
   const GLuint stencilMax = (1 << rb->StencilBits) - 1;
   const GLboolean maskStencil
      = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;

   if (maskStencil) 
      return TRUE;

   if (ctx->Scissor.Enabled)
      return TRUE;

   /* This is correct, but it is necessary to look at the depth clear
    * value held in the surface when it comes time to issue the clear,
    * rather than taking depth and stencil clear values from the
    * current state.
    */
   if (isDS && 
       ctx->DrawBuffer->Visual.depthBits > 0)
      return TRUE;

   return FALSE;
}
Example #5
0
static void
st_Accum(GLcontext *ctx, GLenum op, GLfloat value)
{
   struct st_context *st = ctx->st;
   struct st_renderbuffer *acc_strb
     = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
   struct st_renderbuffer *color_strb
      = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);

   const GLint xpos = ctx->DrawBuffer->_Xmin;
   const GLint ypos = ctx->DrawBuffer->_Ymin;
   const GLint width = ctx->DrawBuffer->_Xmax - xpos;
   const GLint height = ctx->DrawBuffer->_Ymax - ypos;

   if(!acc_strb->data)
      return;
   
   /* make sure color bufs aren't cached */
   st_flush( st, PIPE_FLUSH_RENDER_CACHE, NULL );

   switch (op) {
   case GL_ADD:
      if (value != 0.0F) {
         accum_mad(ctx, 1.0, value, xpos, ypos, width, height, acc_strb);
      }
      break;
   case GL_MULT:
      if (value != 1.0F) {
         accum_mad(ctx, value, 0.0, xpos, ypos, width, height, acc_strb);
      }
      break;
   case GL_ACCUM:
      if (value != 0.0F) {
         accum_accum(st, value, xpos, ypos, width, height, acc_strb, color_strb);
      }
      break;
   case GL_LOAD:
      accum_load(st, value, xpos, ypos, width, height, acc_strb, color_strb);
      break;
   case GL_RETURN:
      accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb);
      break;
   default:
      assert(0);
   }
}
/** Check if we have a front color buffer and if it's been drawn to. */
static INLINE GLboolean
is_front_buffer_dirty(struct st_context *st)
{
   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
   struct st_renderbuffer *strb
      = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
   return strb && strb->defined;
}
Example #7
0
/**
 * gl_renderbuffer::AllocStorage()
 * This is called to allocate the original drawing surface, and
 * during window resize.
 */
static GLboolean
st_renderbuffer_alloc_storage(struct gl_context * ctx,
                              struct gl_renderbuffer *rb,
                              GLenum internalFormat,
                              GLuint width, GLuint height)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = st->pipe->screen;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   enum pipe_format format;
   struct pipe_surface surf_tmpl;

   format = st_choose_renderbuffer_format(screen, internalFormat,
                                          rb->NumSamples);

   if (format == PIPE_FORMAT_NONE) {
      return FALSE;
   }

   /* init renderbuffer fields */
   strb->Base.Width  = width;
   strb->Base.Height = height;
   strb->Base.Format = st_pipe_format_to_mesa_format(format);
   strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
   strb->Base.DataType = st_format_datatype(format);
   strb->format = format;

   strb->defined = GL_FALSE;  /* undefined contents now */

   if (strb->software) {
      size_t size;
      
      free(strb->data);

      assert(strb->format != PIPE_FORMAT_NONE);
      
      strb->stride = util_format_get_stride(strb->format, width);
      size = util_format_get_2d_size(strb->format, strb->stride, height);
      
      strb->data = malloc(size);
      
      return strb->data != NULL;
   }
   else {
      struct pipe_resource template;
    
      /* Free the old surface and texture
       */
      pipe_surface_reference( &strb->surface, NULL );
      pipe_resource_reference( &strb->texture, NULL );
      pipe_sampler_view_reference(&strb->sampler_view, NULL);

      /* Setup new texture template.
       */
      memset(&template, 0, sizeof(template));
Example #8
0
/**
 * gl_renderbuffer::Delete()
 */
static void
st_renderbuffer_delete(struct gl_renderbuffer *rb)
{
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   ASSERT(strb);
   pipe_surface_reference(&strb->surface, NULL);
   pipe_resource_reference(&strb->texture, NULL);
   free(strb->data);
   _mesa_delete_renderbuffer(rb);
}
Example #9
0
/**
 * gl_renderbuffer::Delete()
 */
static void
st_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   if (ctx) {
      struct st_context *st = st_context(ctx);
      pipe_surface_release(st->pipe, &strb->surface);
   }
   pipe_resource_reference(&strb->texture, NULL);
   free(strb->data);
   _mesa_delete_renderbuffer(ctx, rb);
}
Example #10
0
/** Redirect rendering into stfb's surface to a texture image */
int
st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
                 int target, int format, int level)
{
   GET_CURRENT_CONTEXT(ctx);
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   const GLuint unit = ctx->Texture.CurrentUnit;
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   struct st_texture_image *stImage;
   struct st_renderbuffer *strb;
   GLint face = 0, slice = 0;

   assert(surfIndex <= ST_SURFACE_DEPTH);

   strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);

   if (strb->texture_save || strb->surface_save) {
      /* Error! */
      return 0;
   }

   if (target == ST_TEXTURE_2D) {
      texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX];
      texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, level);
      stImage = st_texture_image(texImage);
   }
   else {
      /* unsupported target */
      return 0;
   }

   st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);

   /* save the renderbuffer's surface/texture info */
   pipe_texture_reference(&strb->texture_save, strb->texture);
   pipe_surface_reference(&strb->surface_save, strb->surface);

   /* plug in new surface/texture info */
   pipe_texture_reference(&strb->texture, stImage->pt);
   strb->surface = screen->get_tex_surface(screen, strb->texture,
                                           face, level, slice,
                                           (PIPE_BUFFER_USAGE_GPU_READ |
                                            PIPE_BUFFER_USAGE_GPU_WRITE));

   st->dirty.st |= ST_NEW_FRAMEBUFFER;

   return 1;
}
/**
 * Tell the screen to display the front color buffer on-screen.
 */
static void
display_front_buffer(struct st_context *st)
{
   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
   struct st_renderbuffer *strb
      = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);

   if (strb) {
      /* Hook for copying "fake" frontbuffer if necessary:
       */
      st_manager_flush_frontbuffer(st);
   }
}
Example #12
0
/** Check if we have a front color buffer and if it's been drawn to. */
static INLINE GLboolean
is_front_buffer_dirty(struct st_context *st)
{
   if (st->frontbuffer_status == FRONT_STATUS_DIRTY) {
      return GL_TRUE;
   }
   else {
      GLframebuffer *fb = st->ctx->DrawBuffer;
      struct st_renderbuffer *strb
         = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
      return strb && strb->defined;
   }
}
Example #13
0
/**
 * Called via ctx->Driver.FinishRenderTexture.
 */
static void
st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
   struct st_renderbuffer *strb = st_renderbuffer(rb);

   if (!strb)
      return;

   strb->is_rtt = FALSE;

   /* restore previous framebuffer state */
   st_invalidate_state(ctx, _NEW_BUFFERS);
}
/**
 * Called via ctx->Driver.FinishRenderTexture.
 */
static void
st_finish_render_texture(struct gl_context *ctx,
                         struct gl_renderbuffer_attachment *att)
{
   struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);

   if (!strb)
      return;

   strb->rtt = NULL;

   /* restore previous framebuffer state */
   st_invalidate_state(ctx, _NEW_BUFFERS);
}
Example #15
0
/**
 * gl_renderbuffer::AllocStorage()
 * This is called to allocate the original drawing surface, and
 * during window resize.
 */
static GLboolean
st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
                              GLenum internalFormat,
                              GLuint width, GLuint height)
{
   struct pipe_context *pipe = ctx->st->pipe;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   enum pipe_format format;

   if (strb->format != PIPE_FORMAT_NONE)
      format = strb->format;
   else
      format = st_choose_renderbuffer_format(pipe->screen, internalFormat);
      
   /* init renderbuffer fields */
   strb->Base.Width  = width;
   strb->Base.Height = height;
   init_renderbuffer_bits(strb, format);

   strb->defined = GL_FALSE;  /* undefined contents now */

   if(strb->software) {
      struct pipe_format_block block;
      size_t size;
      
      _mesa_free(strb->data);

      assert(strb->format != PIPE_FORMAT_NONE);
      pf_get_block(strb->format, &block);
      
      strb->stride = pf_get_stride(&block, width);
      size = pf_get_2d_size(&block, strb->stride, height);
      
      strb->data = _mesa_malloc(size);
      
      return strb->data != NULL;
   }
   else {
      struct pipe_texture template;
      unsigned surface_usage;
    
      /* Free the old surface and texture
       */
      pipe_surface_reference( &strb->surface, NULL );
      pipe_texture_reference( &strb->texture, NULL );

      /* Setup new texture template.
       */
      memset(&template, 0, sizeof(template));
Example #16
0
static void
st_BlitFramebuffer(GLcontext *ctx,
                   GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                   GLbitfield mask, GLenum filter)
{
   struct st_context *st = ctx->st;

   const uint pFilter = ((filter == GL_NEAREST)
                         ? PIPE_TEX_MIPFILTER_NEAREST
                         : PIPE_TEX_MIPFILTER_LINEAR);

   if (mask & GL_COLOR_BUFFER_BIT) {
      struct st_renderbuffer *srcRb = 
         st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
      struct st_renderbuffer *dstRb = 
         st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]);
      struct pipe_surface *srcSurf = srcRb->surface;
      struct pipe_surface *dstSurf = dstRb->surface;

      if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
         /* invert Y */
         srcY0 = srcRb->Base.Height - srcY0;
         srcY1 = srcRb->Base.Height - srcY1;

         dstY0 = dstRb->Base.Height - dstY0;
         dstY1 = dstRb->Base.Height - dstY1;
      }

      util_blit_pixels(st->blit,
                       srcSurf, srcX0, srcY0, srcX1, srcY1,
                       dstSurf, dstX0, dstY0, dstX1, dstY1,
                       0.0, pFilter);

   }
}
Example #17
0
/**
 * Flush the front buffer if the current context renders to the front buffer.
 */
void
st_manager_flush_frontbuffer(struct st_context *st)
{
   struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer);
   struct st_renderbuffer *strb = NULL;

   if (stfb)
      strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
   if (!strb)
      return;

   /* never a dummy fb */
   assert(&stfb->Base != _mesa_get_incomplete_framebuffer());
   stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT);
}
Example #18
0
/**
 * Determine if we need to clear the depth buffer by drawing a quad.
 */
static INLINE GLboolean
check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
{
   const struct st_renderbuffer *strb = st_renderbuffer(rb);
   const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);

   if (ctx->Scissor.Enabled)
      return TRUE;

   if (isDS && 
       ctx->DrawBuffer->Visual.stencilBits > 0)
      return TRUE;

   return FALSE;
}
Example #19
0
/**
 * Called via ctx->Driver.UnmapRenderbuffer.
 */
static void
st_UnmapRenderbuffer(struct gl_context *ctx,
                     struct gl_renderbuffer *rb)
{
   struct st_context *st = st_context(ctx);
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_context *pipe = st->pipe;

   if (strb->software) {
      /* software-allocated renderbuffer (probably an accum buffer) */
      return;
   }

   pipe_transfer_unmap(pipe, strb->transfer);
   strb->transfer = NULL;
}
Example #20
0
/**
 * gl_renderbuffer::AllocStorage()
 * This is called to allocate the original drawing surface, and
 * during window resize.
 */
static GLboolean
st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
                              GLenum internalFormat,
                              GLuint width, GLuint height)
{
   struct pipe_context *pipe = ctx->st->pipe;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_texture template;
   unsigned surface_usage;

   /* Free the old surface and texture
    */
   pipe_surface_reference( &strb->surface, NULL );
   pipe_texture_reference( &strb->texture, NULL );


   memset(&template, 0, sizeof(template));
Example #21
0
/**
 * Called by ctx->Driver.RenderTexture
 */
static void
st_render_texture(struct gl_context *ctx,
                  struct gl_framebuffer *fb,
                  struct gl_renderbuffer_attachment *att)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct gl_renderbuffer *rb = att->Renderbuffer;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_resource *pt;

   if (!st_finalize_texture(ctx, pipe, att->Texture))
      return;

   pt = st_get_texobj_resource(att->Texture);
   assert(pt);

   /* point renderbuffer at texobject */
   strb->is_rtt = TRUE;
   strb->rtt_face = att->CubeMapFace;
   strb->rtt_slice = att->Zoffset;
   strb->rtt_layered = att->Layered;
   pipe_resource_reference(&strb->texture, pt);

   pipe_surface_release(pipe, &strb->surface);

   st_update_renderbuffer_surface(st, strb);

   strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);

   /* Invalidate buffer state so that the pipe's framebuffer state
    * gets updated.
    * That's where the new renderbuffer (which we just created) gets
    * passed to the pipe as a (color/depth) render target.
    */
   st_invalidate_state(ctx, _NEW_BUFFERS);


   /* Need to trigger a call to update_framebuffer() since we just
    * attached a new renderbuffer.
    */
   ctx->NewState |= _NEW_BUFFERS;
}
Example #22
0
/**
 * Determine if we need to clear the depth buffer by drawing a quad.
 */
static INLINE GLboolean
check_clear_depth_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
                            boolean ds_separate)
{
   const struct st_renderbuffer *strb = st_renderbuffer(rb);
   const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);

   if (ctx->Scissor.Enabled &&
       (ctx->Scissor.X != 0 ||
        ctx->Scissor.Y != 0 ||
        ctx->Scissor.Width < rb->Width ||
        ctx->Scissor.Height < rb->Height))
      return GL_TRUE;

   if (!ds_separate && isDS && ctx->DrawBuffer->Visual.stencilBits > 0)
      return GL_TRUE;

   return GL_FALSE;
}
Example #23
0
static void
st_egl_image_target_renderbuffer_storage(struct gl_context *ctx,
					 struct gl_renderbuffer *rb,
					 GLeglImageOES image_handle)
{
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct st_egl_image stimg;

   if (st_get_egl_image(ctx, image_handle, PIPE_BIND_RENDER_TARGET,
                        "glEGLImageTargetRenderbufferStorage",
                        &stimg)) {
      struct pipe_context *pipe = st_context(ctx)->pipe;
      struct pipe_surface *ps, surf_tmpl;

      u_surface_default_template(&surf_tmpl, stimg.texture);
      surf_tmpl.format = stimg.format;
      surf_tmpl.u.tex.level = stimg.level;
      surf_tmpl.u.tex.first_layer = stimg.layer;
      surf_tmpl.u.tex.last_layer = stimg.layer;
      ps = pipe->create_surface(pipe, stimg.texture, &surf_tmpl);
      pipe_resource_reference(&stimg.texture, NULL);

      if (!ps)
         return;

      strb->Base.Width = ps->width;
      strb->Base.Height = ps->height;
      strb->Base.Format = st_pipe_format_to_mesa_format(ps->format);
      strb->Base._BaseFormat = st_pipe_format_to_base_format(ps->format);
      strb->Base.InternalFormat = strb->Base._BaseFormat;

      struct pipe_surface **psurf =
         util_format_is_srgb(ps->format) ? &strb->surface_srgb :
                                           &strb->surface_linear;

      pipe_surface_reference(psurf, ps);
      strb->surface = *psurf;
      pipe_resource_reference(&strb->texture, ps->texture);

      pipe_surface_reference(&ps, NULL);
   }
}
Example #24
0
/**
 * Tell the screen to display the front color buffer on-screen.
 */
static void
display_front_buffer(struct st_context *st)
{
   GLframebuffer *fb = st->ctx->DrawBuffer;
   struct st_renderbuffer *strb
      = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);

   if (strb) {
      struct pipe_surface *front_surf = strb->surface;
      
      /* Hook for copying "fake" frontbuffer if necessary:
       */
      st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf,
                                           st->pipe->priv );

      /*
        st->frontbuffer_status = FRONT_STATUS_UNDEFINED;
      */
   }
}
Example #25
0
/**
 * Update the attachments to validate by looping the existing renderbuffers.
 */
static void
st_framebuffer_update_attachments(struct st_framebuffer *stfb)
{
   gl_buffer_index idx;

   stfb->num_statts = 0;
   for (idx = 0; idx < BUFFER_COUNT; idx++) {
      struct st_renderbuffer *strb;
      enum st_attachment_type statt;

      strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
      if (!strb || strb->software)
         continue;

      statt = buffer_index_to_attachment(idx);
      if (statt != ST_ATTACHMENT_INVALID &&
          st_visual_have_buffers(stfb->iface->visual, 1 << statt))
         stfb->statts[stfb->num_statts++] = statt;
   }
   stfb->stamp++;
}
Example #26
0
static GLboolean
st_renderbuffer_alloc_sw_storage(struct gl_context * ctx,
                                 struct gl_renderbuffer *rb,
                                 GLenum internalFormat,
                                 GLuint width, GLuint height)
{
   struct st_context *st = st_context(ctx);
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   enum pipe_format format;
   size_t size;

   free(strb->data);
   strb->data = NULL;

   if (internalFormat == GL_RGBA16_SNORM) {
      /* Special case for software accum buffers.  Otherwise, if the
       * call to st_choose_renderbuffer_format() fails (because the
       * driver doesn't support signed 16-bit/channel colors) we'd
       * just return without allocating the software accum buffer.
       */
      format = PIPE_FORMAT_R16G16B16A16_SNORM;
   }
   else {
      format = st_choose_renderbuffer_format(st, internalFormat, 0);

      /* Not setting gl_renderbuffer::Format here will cause
       * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
       */
      if (format == PIPE_FORMAT_NONE) {
         return GL_TRUE;
      }
   }

   strb->Base.Format = st_pipe_format_to_mesa_format(format);

   size = _mesa_format_image_size(strb->Base.Format, width, height, 1);
   strb->data = malloc(size);
   return strb->data != NULL;
}
Example #27
0
void
st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
{
   struct st_renderbuffer *acc_strb = st_renderbuffer(rb);
   const GLint xpos = ctx->DrawBuffer->_Xmin;
   const GLint ypos = ctx->DrawBuffer->_Ymin;
   const GLint width = ctx->DrawBuffer->_Xmax - xpos;
   const GLint height = ctx->DrawBuffer->_Ymax - ypos;
   size_t stride = acc_strb->stride;
   GLubyte *data = acc_strb->data;

   if(!data)
      return;
   
   switch (acc_strb->format) {
   case PIPE_FORMAT_R16G16B16A16_SNORM:
      {
         GLshort r = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]);
         GLshort g = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]);
         GLshort b = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]);
         GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]);
         int i, j;
         for (i = 0; i < height; i++) {
            GLshort *dst = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
            for (j = 0; j < width; j++) {
               dst[0] = r;
               dst[1] = g;
               dst[2] = b;
               dst[3] = a;
               dst += 4;
            }
         }
      }
      break;
   default:
      _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()");
   }
}
Example #28
0
/**
 * Validate a framebuffer to make sure up-to-date pipe_textures are used.
 * The context we need to pass in is s dummy context needed only to be
 * able to get a pipe context to create pipe surfaces, and to have a
 * context to call _mesa_resize_framebuffer():
 * (That should probably be rethought, since those surfaces become
 * drawable state, not context state, and can be freed by another pipe
 * context).
 */
static void
st_framebuffer_validate(struct st_framebuffer *stfb,
                        struct st_context *st)
{
   struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
   uint width, height;
   unsigned i;
   boolean changed = FALSE;
   int32_t new_stamp = p_atomic_read(&stfb->iface->stamp);

   if (stfb->iface_stamp == new_stamp)
      return;

   /* validate the fb */
   do {
      if (!stfb->iface->validate(stfb->iface, stfb->statts,
				 stfb->num_statts, textures))
	 return;

      stfb->iface_stamp = new_stamp;
      new_stamp = p_atomic_read(&stfb->iface->stamp);
   } while(stfb->iface_stamp != new_stamp);

   width = stfb->Base.Width;
   height = stfb->Base.Height;

   for (i = 0; i < stfb->num_statts; i++) {
      struct st_renderbuffer *strb;
      struct pipe_surface *ps, surf_tmpl;
      gl_buffer_index idx;

      if (!textures[i])
         continue;

      idx = attachment_to_buffer_index(stfb->statts[i]);
      if (idx >= BUFFER_COUNT) {
         pipe_resource_reference(&textures[i], NULL);
         continue;
      }

      strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
      assert(strb);
      if (strb->texture == textures[i]) {
         pipe_resource_reference(&textures[i], NULL);
         continue;
      }

      u_surface_default_template(&surf_tmpl, textures[i],
                                 PIPE_BIND_RENDER_TARGET);
      ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl);
      if (ps) {
         pipe_surface_reference(&strb->surface, ps);
         pipe_resource_reference(&strb->texture, ps->texture);
         /* ownership transfered */
         pipe_surface_reference(&ps, NULL);

         changed = TRUE;

         strb->Base.Width = strb->surface->width;
         strb->Base.Height = strb->surface->height;

         width = strb->Base.Width;
         height = strb->Base.Height;
      }

      pipe_resource_reference(&textures[i], NULL);
   }

   if (changed) {
      ++stfb->stamp;
      _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
   }
}
Example #29
0
/**
 * This uses a blit to copy the read buffer to a texture format which matches
 * the format and type combo and then a fast read-back is done using memcpy.
 * We can do arbitrary X/Y/Z/W/0/1 swizzling here as long as there is
 * a format which matches the swizzling.
 *
 * If such a format isn't available, we fall back to _mesa_readpixels.
 *
 * NOTE: Some drivers use a blit to convert between tiled and linear
 *       texture layouts during texture uploads/downloads, so the blit
 *       we do here should be free in such cases.
 */
static void
st_readpixels(struct gl_context *ctx, GLint x, GLint y,
              GLsizei width, GLsizei height,
              GLenum format, GLenum type,
              const struct gl_pixelstore_attrib *pack,
              GLvoid *pixels)
{
   struct st_context *st = st_context(ctx);
   struct gl_renderbuffer *rb =
         _mesa_get_read_renderbuffer_for_format(ctx, format);
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_resource *src;
   struct pipe_resource *dst = NULL;
   struct pipe_resource dst_templ;
   enum pipe_format dst_format, src_format;
   struct pipe_blit_info blit;
   unsigned bind = PIPE_BIND_TRANSFER_READ;
   struct pipe_transfer *tex_xfer;
   ubyte *map = NULL;

   /* Validate state (to be sure we have up-to-date framebuffer surfaces)
    * and flush the bitmap cache prior to reading. */
   st_validate_state(st);
   st_flush_bitmap_cache(st);

   if (!st->prefer_blit_based_texture_transfer) {
      goto fallback;
   }

   /* This must be done after state validation. */
   src = strb->texture;

   /* XXX Fallback for depth-stencil formats due to an incomplete
    * stencil blit implementation in some drivers. */
   if (format == GL_DEPTH_STENCIL) {
      goto fallback;
   }

   /* We are creating a texture of the size of the region being read back.
    * Need to check for NPOT texture support. */
   if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) &&
       (!util_is_power_of_two(width) ||
        !util_is_power_of_two(height))) {
      goto fallback;
   }

   /* If the base internal format and the texture format don't match, we have
    * to use the slow path. */
   if (rb->_BaseFormat !=
       _mesa_get_format_base_format(rb->Format)) {
      goto fallback;
   }

   /* See if the texture format already matches the format and type,
    * in which case the memcpy-based fast path will likely be used and
    * we don't have to blit. */
   if (_mesa_format_matches_format_and_type(rb->Format, format,
                                            type, pack->SwapBytes)) {
      goto fallback;
   }

   if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_TRUE)) {
      goto fallback;
   }

   /* Convert the source format to what is expected by ReadPixels
    * and see if it's supported. */
   src_format = util_format_linear(src->format);
   src_format = util_format_luminance_to_red(src_format);
   src_format = util_format_intensity_to_red(src_format);

   if (!src_format ||
       !screen->is_format_supported(screen, src_format, src->target,
                                    src->nr_samples,
                                    PIPE_BIND_SAMPLER_VIEW)) {
      goto fallback;
   }

   if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)
      bind |= PIPE_BIND_DEPTH_STENCIL;
   else
      bind |= PIPE_BIND_RENDER_TARGET;

   /* Choose the destination format by finding the best match
    * for the format+type combo. */
   dst_format = st_choose_matching_format(screen, bind, format, type,
                                          pack->SwapBytes);
   if (dst_format == PIPE_FORMAT_NONE) {
      goto fallback;
   }

   /* create the destination texture */
   memset(&dst_templ, 0, sizeof(dst_templ));
   dst_templ.target = PIPE_TEXTURE_2D;
   dst_templ.format = dst_format;
   dst_templ.bind = bind;
   dst_templ.usage = PIPE_USAGE_STAGING;

   st_gl_texture_dims_to_pipe_dims(GL_TEXTURE_2D, width, height, 1,
                                   &dst_templ.width0, &dst_templ.height0,
                                   &dst_templ.depth0, &dst_templ.array_size);

   dst = screen->resource_create(screen, &dst_templ);
   if (!dst) {
      goto fallback;
   }

   memset(&blit, 0, sizeof(blit));
   blit.src.resource = src;
   blit.src.level = strb->surface->u.tex.level;
   blit.src.format = src_format;
   blit.dst.resource = dst;
   blit.dst.level = 0;
   blit.dst.format = dst->format;
   blit.src.box.x = x;
   blit.dst.box.x = 0;
   blit.src.box.y = y;
   blit.dst.box.y = 0;
   blit.src.box.z = strb->surface->u.tex.first_layer;
   blit.dst.box.z = 0;
   blit.src.box.width = blit.dst.box.width = width;
   blit.src.box.height = blit.dst.box.height = height;
   blit.src.box.depth = blit.dst.box.depth = 1;
   blit.mask = st_get_blit_mask(rb->_BaseFormat, format);
   blit.filter = PIPE_TEX_FILTER_NEAREST;
   blit.scissor_enable = FALSE;

   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
      blit.src.box.y = rb->Height - blit.src.box.y;
      blit.src.box.height = -blit.src.box.height;
   }

   /* blit */
   st->pipe->blit(st->pipe, &blit);

   /* map resources */
   pixels = _mesa_map_pbo_dest(ctx, pack, pixels);

   map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ,
                              0, 0, 0, width, height, 1, &tex_xfer);
   if (!map) {
      _mesa_unmap_pbo_dest(ctx, pack);
      pipe_resource_reference(&dst, NULL);
      goto fallback;
   }

   /* memcpy data into a user buffer */
   {
      const uint bytesPerRow = width * util_format_get_blocksize(dst_format);
      GLuint row;

      for (row = 0; row < (unsigned) height; row++) {
         GLvoid *dest = _mesa_image_address3d(pack, pixels,
                                              width, height, format,
                                              type, 0, row, 0);
         memcpy(dest, map, bytesPerRow);
         map += tex_xfer->stride;
      }
   }

   pipe_transfer_unmap(pipe, tex_xfer);
   _mesa_unmap_pbo_dest(ctx, pack);
   pipe_resource_reference(&dst, NULL);
   return;

fallback:
   _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels);
}
Example #30
0
static void
st_BlitFramebuffer(struct gl_context *ctx,
                   struct gl_framebuffer *readFB,
                   struct gl_framebuffer *drawFB,
                   GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                   GLbitfield mask, GLenum filter)
{
   const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
                                    GL_STENCIL_BUFFER_BIT);
   struct st_context *st = st_context(ctx);
   const uint pFilter = ((filter == GL_NEAREST)
                         ? PIPE_TEX_FILTER_NEAREST
                         : PIPE_TEX_FILTER_LINEAR);
   struct {
      GLint srcX0, srcY0, srcX1, srcY1;
      GLint dstX0, dstY0, dstX1, dstY1;
   } clip;
   struct pipe_blit_info blit;

   st_manager_validate_framebuffers(st);

   /* Make sure bitmap rendering has landed in the framebuffers */
   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   clip.srcX0 = srcX0;
   clip.srcY0 = srcY0;
   clip.srcX1 = srcX1;
   clip.srcY1 = srcY1;
   clip.dstX0 = dstX0;
   clip.dstY0 = dstY0;
   clip.dstX1 = dstX1;
   clip.dstY1 = dstY1;

   /* NOTE: If the src and dst dimensions don't match, we cannot simply adjust
    * the integer coordinates to account for clipping (or scissors) because that
    * would make us cut off fractional parts, affecting the result of the blit.
    *
    * XXX: This should depend on mask !
    */
   if (!_mesa_clip_blit(ctx, readFB, drawFB,
                        &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
                        &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
      return; /* nothing to draw/blit */
   }
   memset(&blit, 0, sizeof(struct pipe_blit_info));
   blit.scissor_enable =
      (dstX0 != clip.dstX0) ||
      (dstY0 != clip.dstY0) ||
      (dstX1 != clip.dstX1) ||
      (dstY1 != clip.dstY1);

   if (st_fb_orientation(drawFB) == Y_0_TOP) {
      /* invert Y for dest */
      dstY0 = drawFB->Height - dstY0;
      dstY1 = drawFB->Height - dstY1;
      /* invert Y for clip */
      clip.dstY0 = drawFB->Height - clip.dstY0;
      clip.dstY1 = drawFB->Height - clip.dstY1;
   }
   if (blit.scissor_enable) {
      blit.scissor.minx = MIN2(clip.dstX0, clip.dstX1);
      blit.scissor.miny = MIN2(clip.dstY0, clip.dstY1);
      blit.scissor.maxx = MAX2(clip.dstX0, clip.dstX1);
      blit.scissor.maxy = MAX2(clip.dstY0, clip.dstY1);
#if 0
      debug_printf("scissor = (%i,%i)-(%i,%i)\n",
                   blit.scissor.minx,blit.scissor.miny,
                   blit.scissor.maxx,blit.scissor.maxy);
#endif
   }

   if (st_fb_orientation(readFB) == Y_0_TOP) {
      /* invert Y for src */
      srcY0 = readFB->Height - srcY0;
      srcY1 = readFB->Height - srcY1;
   }

   if (srcY0 > srcY1 && dstY0 > dstY1) {
      /* Both src and dst are upside down.  Swap Y to make it
       * right-side up to increase odds of using a fast path.
       * Recall that all Gallium raster coords have Y=0=top.
       */
      GLint tmp;
      tmp = srcY0;
      srcY0 = srcY1;
      srcY1 = tmp;
      tmp = dstY0;
      dstY0 = dstY1;
      dstY1 = tmp;
   }

   blit.src.box.depth = 1;
   blit.dst.box.depth = 1;

   /* Destination dimensions have to be positive: */
   if (dstX0 < dstX1) {
      blit.dst.box.x = dstX0;
      blit.src.box.x = srcX0;
      blit.dst.box.width = dstX1 - dstX0;
      blit.src.box.width = srcX1 - srcX0;
   } else {
      blit.dst.box.x = dstX1;
      blit.src.box.x = srcX1;
      blit.dst.box.width = dstX0 - dstX1;
      blit.src.box.width = srcX0 - srcX1;
   }
   if (dstY0 < dstY1) {
      blit.dst.box.y = dstY0;
      blit.src.box.y = srcY0;
      blit.dst.box.height = dstY1 - dstY0;
      blit.src.box.height = srcY1 - srcY0;
   } else {
      blit.dst.box.y = dstY1;
      blit.src.box.y = srcY1;
      blit.dst.box.height = dstY0 - dstY1;
      blit.src.box.height = srcY0 - srcY1;
   }

   if (drawFB != ctx->WinSysDrawBuffer)
      st_window_rectangles_to_blit(ctx, &blit);

   blit.filter = pFilter;
   blit.render_condition_enable = TRUE;
   blit.alpha_blend = FALSE;

   if (mask & GL_COLOR_BUFFER_BIT) {
      struct gl_renderbuffer_attachment *srcAtt =
         &readFB->Attachment[readFB->_ColorReadBufferIndex];

      blit.mask = PIPE_MASK_RGBA;

      if (srcAtt->Type == GL_TEXTURE) {
         struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture);
         GLuint i;

         if (!srcObj || !srcObj->pt) {
            return;
         }

         for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
            struct st_renderbuffer *dstRb =
               st_renderbuffer(drawFB->_ColorDrawBuffers[i]);

            if (dstRb) {
               struct pipe_surface *dstSurf = dstRb->surface;

               if (dstSurf) {
                  blit.dst.resource = dstSurf->texture;
                  blit.dst.level = dstSurf->u.tex.level;
                  blit.dst.box.z = dstSurf->u.tex.first_layer;
                  blit.dst.format = dstSurf->format;

                  blit.src.resource = srcObj->pt;
                  blit.src.level = srcAtt->TextureLevel;
                  blit.src.box.z = srcAtt->Zoffset + srcAtt->CubeMapFace;
                  blit.src.format = srcObj->pt->format;

                  st_adjust_blit_for_srgb(&blit, ctx->Color.sRGBEnabled);

                  st->pipe->blit(st->pipe, &blit);
                  dstRb->defined = true; /* front buffer tracking */
               }
            }
         }
      }
      else {
         struct st_renderbuffer *srcRb =
            st_renderbuffer(readFB->_ColorReadBuffer);
         struct pipe_surface *srcSurf;
         GLuint i;

         if (!srcRb || !srcRb->surface) {
            return;
         }

         srcSurf = srcRb->surface;

         for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
            struct st_renderbuffer *dstRb =
               st_renderbuffer(drawFB->_ColorDrawBuffers[i]);

            if (dstRb) {
               struct pipe_surface *dstSurf = dstRb->surface;

               if (dstSurf) {
                  blit.dst.resource = dstSurf->texture;
                  blit.dst.level = dstSurf->u.tex.level;
                  blit.dst.box.z = dstSurf->u.tex.first_layer;
                  blit.dst.format = dstSurf->format;

                  blit.src.resource = srcSurf->texture;
                  blit.src.level = srcSurf->u.tex.level;
                  blit.src.box.z = srcSurf->u.tex.first_layer;
                  blit.src.format = srcSurf->format;

                  st_adjust_blit_for_srgb(&blit, ctx->Color.sRGBEnabled);

                  st->pipe->blit(st->pipe, &blit);
                  dstRb->defined = true; /* front buffer tracking */
               }
            }
         }
      }
   }

   if (mask & depthStencil) {
      /* depth and/or stencil blit */

      /* get src/dst depth surfaces */
      struct st_renderbuffer *srcDepthRb =
         st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct st_renderbuffer *dstDepthRb = 
         st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct pipe_surface *dstDepthSurf =
         dstDepthRb ? dstDepthRb->surface : NULL;

      struct st_renderbuffer *srcStencilRb =
         st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
      struct st_renderbuffer *dstStencilRb =
         st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);
      struct pipe_surface *dstStencilSurf =
         dstStencilRb ? dstStencilRb->surface : NULL;

      if (_mesa_has_depthstencil_combined(readFB) &&
          _mesa_has_depthstencil_combined(drawFB)) {
         blit.mask = 0;
         if (mask & GL_DEPTH_BUFFER_BIT)
            blit.mask |= PIPE_MASK_Z;
         if (mask & GL_STENCIL_BUFFER_BIT)
            blit.mask |= PIPE_MASK_S;

         blit.dst.resource = dstDepthSurf->texture;
         blit.dst.level = dstDepthSurf->u.tex.level;
         blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
         blit.dst.format = dstDepthSurf->format;

         blit.src.resource = srcDepthRb->texture;
         blit.src.level = srcDepthRb->surface->u.tex.level;
         blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
         blit.src.format = srcDepthRb->surface->format;

         st->pipe->blit(st->pipe, &blit);
      }
      else {
         /* blitting depth and stencil separately */

         if (mask & GL_DEPTH_BUFFER_BIT) {
            blit.mask = PIPE_MASK_Z;

            blit.dst.resource = dstDepthSurf->texture;
            blit.dst.level = dstDepthSurf->u.tex.level;
            blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
            blit.dst.format = dstDepthSurf->format;

            blit.src.resource = srcDepthRb->texture;
            blit.src.level = srcDepthRb->surface->u.tex.level;
            blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
            blit.src.format = srcDepthRb->surface->format;

            st->pipe->blit(st->pipe, &blit);
         }

         if (mask & GL_STENCIL_BUFFER_BIT) {
            blit.mask = PIPE_MASK_S;

            blit.dst.resource = dstStencilSurf->texture;
            blit.dst.level = dstStencilSurf->u.tex.level;
            blit.dst.box.z = dstStencilSurf->u.tex.first_layer;
            blit.dst.format = dstStencilSurf->format;

            blit.src.resource = srcStencilRb->texture;
            blit.src.level = srcStencilRb->surface->u.tex.level;
            blit.src.box.z = srcStencilRb->surface->u.tex.first_layer;
            blit.src.format = srcStencilRb->surface->format;

            st->pipe->blit(st->pipe, &blit);
         }
      }
   }
}