Exemple #1
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;
}
/**
 * Update framebuffer state (color, depth, stencil, etc. buffers)
 */
static void
update_framebuffer_state( struct st_context *st )
{
    struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer;
    struct gl_framebuffer *fb = st->ctx->DrawBuffer;
    struct st_renderbuffer *strb;
    GLuint i;

    st_flush_bitmap_cache(st);

    st->state.fb_orientation = st_fb_orientation(fb);
    framebuffer->width = fb->Width;
    framebuffer->height = fb->Height;

    /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/

    /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
     * to determine which surfaces to draw to
     */
    framebuffer->nr_cbufs = fb->_NumColorDrawBuffers;

    for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
        pipe_surface_reference(&framebuffer->cbufs[i], NULL);

        strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);

        if (strb) {
            if (strb->is_rtt ||
                    (strb->texture && util_format_is_srgb(strb->texture->format))) {
                /* rendering to a GL texture, may have to update surface */
                st_update_renderbuffer_surface(st, strb);
            }

            if (strb->surface) {
                pipe_surface_reference(&framebuffer->cbufs[i], strb->surface);
            }
            strb->defined = GL_TRUE; /* we'll be drawing something */
        }
    }

    for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
        pipe_surface_reference(&framebuffer->cbufs[i], NULL);
    }

    /*
     * Depth/Stencil renderbuffer/surface.
     */
    strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
    if (strb) {
        if (strb->is_rtt) {
            /* rendering to a GL texture, may have to update surface */
            st_update_renderbuffer_surface(st, strb);
        }
        pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
    }
    else {
        strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
        if (strb) {
            assert(strb->surface);
            pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
        }
        else
            pipe_surface_reference(&framebuffer->zsbuf, NULL);
    }

#ifdef DEBUG
    /* Make sure the resource binding flags were set properly */
    for (i = 0; i < framebuffer->nr_cbufs; i++) {
        assert(!framebuffer->cbufs[i] ||
               framebuffer->cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET);
    }
    if (framebuffer->zsbuf) {
        assert(framebuffer->zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL);
    }
#endif

    cso_set_framebuffer(st->cso_context, framebuffer);
}
/**
 * Update framebuffer state (color, depth, stencil, etc. buffers)
 */
void
st_update_framebuffer_state( struct st_context *st )
{
   struct pipe_framebuffer_state framebuffer;
   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
   struct st_renderbuffer *strb;
   GLuint i;

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   st->state.fb_orientation = st_fb_orientation(fb);

   /**
    * Quantize the derived default number of samples:
    *
    * A query to the driver of supported MSAA values the
    * hardware supports is done as to legalize the number
    * of application requested samples, NumSamples.
    * See commit eb9cf3c for more information.
    */
   fb->DefaultGeometry._NumSamples =
      framebuffer_quantize_num_samples(st, fb->DefaultGeometry.NumSamples);

   framebuffer.width  = _mesa_geometric_width(fb);
   framebuffer.height = _mesa_geometric_height(fb);
   framebuffer.samples = _mesa_geometric_samples(fb);
   framebuffer.layers = _mesa_geometric_layers(fb);

   /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
    * to determine which surfaces to draw to
    */
   framebuffer.nr_cbufs = fb->_NumColorDrawBuffers;

   for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
      framebuffer.cbufs[i] = NULL;
      strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);

      if (strb) {
         if (strb->is_rtt || (strb->texture &&
             _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB)) {
            /* rendering to a GL texture, may have to update surface */
            st_update_renderbuffer_surface(st, strb);
         }

         if (strb->surface) {
            framebuffer.cbufs[i] = strb->surface;
            update_framebuffer_size(&framebuffer, strb->surface);
         }
         strb->defined = GL_TRUE; /* we'll be drawing something */
      }
   }

   for (i = framebuffer.nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
      framebuffer.cbufs[i] = NULL;
   }

   /* Remove trailing GL_NONE draw buffers. */
   while (framebuffer.nr_cbufs &&
          !framebuffer.cbufs[framebuffer.nr_cbufs-1]) {
      framebuffer.nr_cbufs--;
   }

   /*
    * Depth/Stencil renderbuffer/surface.
    */
   strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
   if (!strb)
      strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);

   if (strb) {
      if (strb->is_rtt) {
         /* rendering to a GL texture, may have to update surface */
         st_update_renderbuffer_surface(st, strb);
      }
      framebuffer.zsbuf = strb->surface;
      update_framebuffer_size(&framebuffer, strb->surface);
   }
   else
      framebuffer.zsbuf = NULL;

#ifdef DEBUG
   /* Make sure the resource binding flags were set properly */
   for (i = 0; i < framebuffer.nr_cbufs; i++) {
      assert(!framebuffer.cbufs[i] ||
             framebuffer.cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET);
   }
   if (framebuffer.zsbuf) {
      assert(framebuffer.zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL);
   }
#endif

   if (framebuffer.width == USHRT_MAX)
      framebuffer.width = 0;
   if (framebuffer.height == USHRT_MAX)
      framebuffer.height = 0;

   cso_set_framebuffer(st->cso_context, &framebuffer);

   st->state.fb_width = framebuffer.width;
   st->state.fb_height = framebuffer.height;
   st->state.fb_num_samples = util_framebuffer_get_num_samples(&framebuffer);
   st->state.fb_num_layers = util_framebuffer_get_num_layers(&framebuffer);
   st->state.fb_num_cb = framebuffer.nr_cbufs;
}
Exemple #4
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];
      GLuint i;

      blit.mask = PIPE_MASK_RGBA;

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

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

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

         if (!ctx->Color.sRGBEnabled)
            blit.src.format = util_format_linear(blit.src.format);
      }
      else {
         struct st_renderbuffer *srcRb =
            st_renderbuffer(readFB->_ColorReadBuffer);
         struct pipe_surface *srcSurf;

         if (!srcRb)
            return;

         st_update_renderbuffer_surface(st, srcRb);

         if (!srcRb->surface)
            return;

         srcSurf = srcRb->surface;

         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;
      }

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

         if (dstRb) {
            struct pipe_surface *dstSurf;

            st_update_renderbuffer_surface(st, dstRb);

            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;

               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);
         }
      }
   }
}