Esempio n. 1
0
static void st_dispatch_compute_common(struct gl_context *ctx,
                                       const GLuint *num_groups,
                                       const GLuint *group_size,
                                       struct pipe_resource *indirect,
                                       GLintptr indirect_offset)
{
   struct gl_shader_program *prog =
      ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_grid_info info = { 0 };

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   if (ctx->NewState)
      _mesa_update_state(ctx);

   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_COMPUTE_STATE_MASK ||
       st->compute_shader_may_be_dirty)
      st_validate_state(st, ST_PIPELINE_COMPUTE);

   for (unsigned i = 0; i < 3; i++) {
      info.block[i] = group_size ? group_size[i] : prog->Comp.LocalSize[i];
      info.grid[i]  = num_groups ? num_groups[i] : 0;
   }

   if (indirect) {
      info.indirect = indirect;
      info.indirect_offset = indirect_offset;
   }

   pipe->launch_grid(pipe, &info);
}
Esempio n. 2
0
/**
 * Try to accumulate this glBitmap call in the bitmap cache.
 * \return  GL_TRUE for success, GL_FALSE if bitmap is too large, etc.
 */
static GLboolean
accum_bitmap(struct st_context *st,
             GLint x, GLint y, GLsizei width, GLsizei height,
             const struct gl_pixelstore_attrib *unpack,
             const GLubyte *bitmap )
{
   struct bitmap_cache *cache = st->bitmap.cache;
   int px = -999, py = -999;
   const GLfloat z = st->ctx->Current.RasterPos[2];

   if (width > BITMAP_CACHE_WIDTH ||
       height > BITMAP_CACHE_HEIGHT)
      return GL_FALSE; /* too big to cache */

   if (!cache->empty) {
      px = x - cache->xpos;  /* pos in buffer */
      py = y - cache->ypos;
      if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
          py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
          !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
          ((fabs(z - cache->zpos) > Z_EPSILON))) {
         /* This bitmap would extend beyond cache bounds, or the bitmap
          * color is changing
          * so flush and continue.
          */
         st_flush_bitmap_cache(st);
      }
   }

   if (cache->empty) {
      /* Initialize.  Center bitmap vertically in the buffer. */
      px = 0;
      py = (BITMAP_CACHE_HEIGHT - height) / 2;
      cache->xpos = x;
      cache->ypos = y - py;
      cache->zpos = z;
      cache->empty = GL_FALSE;
      COPY_4FV(cache->color, st->ctx->Current.RasterColor);
   }

   assert(px != -999);
   assert(py != -999);

   if (x < cache->xmin)
      cache->xmin = x;
   if (y < cache->ymin)
      cache->ymin = y;
   if (x + width > cache->xmax)
      cache->xmax = x + width;
   if (y + height > cache->ymax)
      cache->ymax = y + height;

   /* create the transfer if needed */
   create_cache_trans(st);

   unpack_bitmap(st, px, py, width, height, unpack, bitmap,
                 cache->buffer, BITMAP_CACHE_WIDTH);

   return GL_TRUE; /* accumulated */
}
Esempio n. 3
0
/**
 * Called via ctx->Driver.BeginConditionalRender()
 */
static void
st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q,
                          GLenum mode)
{
   struct st_query_object *stq = st_query_object(q);
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   uint m;

   st_flush_bitmap_cache(st);

   switch (mode) {
   case GL_QUERY_WAIT:
      m = PIPE_RENDER_COND_WAIT;
      break;
   case GL_QUERY_NO_WAIT:
      m = PIPE_RENDER_COND_NO_WAIT;
      break;
   case GL_QUERY_BY_REGION_WAIT:
      m = PIPE_RENDER_COND_BY_REGION_WAIT;
      break;
   case GL_QUERY_BY_REGION_NO_WAIT:
      m = PIPE_RENDER_COND_BY_REGION_NO_WAIT;
      break;
   default:
      assert(0 && "bad mode in st_BeginConditionalRender");
      m = PIPE_RENDER_COND_WAIT;
   }

   st->render_condition = stq->pq;
   st->condition_mode = m;

   pipe->render_condition(pipe, stq->pq, m);
}
Esempio n. 4
0
/**
 * Flush bitmap cache and release vertex buffer.
 */
void
st_flush_bitmap( struct st_context *st )
{
   st_flush_bitmap_cache(st);

   /* Release vertex buffer to avoid synchronous rendering if we were
    * to map it in the next frame.
    */
   pipe_resource_reference(&st->bitmap.vbuf, NULL);
   st->bitmap.vbuf_slot = 0;
}
void st_flush(struct st_context *st,
              struct pipe_fence_handle **fence,
              enum pipe_flush_flags flags)
{
   FLUSH_VERTICES(st->ctx, 0);
   FLUSH_CURRENT(st->ctx, 0);

   st_flush_bitmap_cache(st);

   st->pipe->flush(st->pipe, fence, flags);
}
Esempio n. 6
0
/**
 * Called via ctx->Driver.BeginConditionalRender()
 */
static void
st_EndConditionalRender(struct gl_context *ctx, struct gl_query_object *q)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   (void) q;

   st_flush_bitmap_cache(st);

   pipe->render_condition(pipe, NULL, 0);
   st->render_condition = NULL;
}
static void
st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
{
   struct pipe_context *pipe = st_context(ctx)->pipe;
   struct st_query_object *stq = st_query_object(q);

   st_flush_bitmap_cache(st_context(ctx));

   if (q->Target == GL_TIMESTAMP && !stq->pq) {
      stq->pq = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP);
      stq->type = PIPE_QUERY_TIMESTAMP;
   }

   pipe->end_query(pipe, stq->pq);
}
static void
st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
{
   struct pipe_context *pipe = st_context(ctx)->pipe;
   struct st_query_object *stq = st_query_object(q);
   unsigned type;

   st_flush_bitmap_cache(st_context(ctx));

   /* convert GL query type to Gallium query type */
   switch (q->Target) {
   case GL_ANY_SAMPLES_PASSED:
      /* fall-through */
   case GL_SAMPLES_PASSED_ARB:
      type = PIPE_QUERY_OCCLUSION_COUNTER;
      break;
   case GL_PRIMITIVES_GENERATED:
      type = PIPE_QUERY_PRIMITIVES_GENERATED;
      break;
   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
      type = PIPE_QUERY_PRIMITIVES_EMITTED;
      break;
   case GL_TIME_ELAPSED_EXT:
      type = PIPE_QUERY_TIME_ELAPSED;
      break;
   default:
      assert(0 && "unexpected query target in st_BeginQuery()");
      return;
   }

   if (stq->pq && stq->type != type) {
      /* free old query of different type */
      pipe->destroy_query(pipe, stq->pq);
      stq->pq = NULL;
      stq->type = PIPE_QUERY_TYPES; /* an invalid value */
   }

   if (!stq->pq) {
      stq->pq = pipe->create_query(pipe, type);
      stq->type = type;
   }

   assert(stq->type == type);

   pipe->begin_query(pipe, stq->pq);
}
Esempio n. 9
0
static void
st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
{
   struct pipe_context *pipe = st_context(ctx)->pipe;
   struct st_query_object *stq = st_query_object(q);
   bool ret = false;

   st_flush_bitmap_cache(st_context(ctx));

   if ((q->Target == GL_TIMESTAMP ||
        q->Target == GL_TIME_ELAPSED) &&
       !stq->pq) {
      stq->pq = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP, 0);
      stq->type = PIPE_QUERY_TIMESTAMP;
   }

   if (stq->pq)
      ret = pipe->end_query(pipe, stq->pq);

   if (!ret) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEndQuery");
      return;
   }
}
Esempio n. 10
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);
         }
      }
   }
}
Esempio n. 11
0
static void
st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct st_query_object *stq = st_query_object(q);
   unsigned type;

   st_flush_bitmap_cache(st_context(ctx));

   /* convert GL query type to Gallium query type */
   switch (q->Target) {
   case GL_ANY_SAMPLES_PASSED:
   case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
      /* fall-through */
   case GL_SAMPLES_PASSED_ARB:
      type = PIPE_QUERY_OCCLUSION_COUNTER;
      break;
   case GL_PRIMITIVES_GENERATED:
      type = PIPE_QUERY_PRIMITIVES_GENERATED;
      break;
   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
      type = PIPE_QUERY_PRIMITIVES_EMITTED;
      break;
   case GL_TIME_ELAPSED:
      if (st->has_time_elapsed)
         type = PIPE_QUERY_TIME_ELAPSED;
      else
         type = PIPE_QUERY_TIMESTAMP;
      break;
   default:
      assert(0 && "unexpected query target in st_BeginQuery()");
      return;
   }

   if (stq->type != type) {
      /* free old query of different type */
      if (stq->pq) {
         pipe->destroy_query(pipe, stq->pq);
         stq->pq = NULL;
      }
      if (stq->pq_begin) {
         pipe->destroy_query(pipe, stq->pq_begin);
         stq->pq_begin = NULL;
      }
      stq->type = PIPE_QUERY_TYPES; /* an invalid value */
   }

   if (q->Target == GL_TIME_ELAPSED &&
       type == PIPE_QUERY_TIMESTAMP) {
      /* Determine time elapsed by emitting two timestamp queries. */
      if (!stq->pq_begin) {
         stq->pq_begin = pipe->create_query(pipe, type);
         stq->type = type;
      }
      pipe->end_query(pipe, stq->pq_begin);
   } else {
      if (!stq->pq) {
         stq->pq = pipe->create_query(pipe, type);
         stq->type = type;
      }
      pipe->begin_query(pipe, stq->pq);
   }
   assert(stq->type == type);
}
Esempio n. 12
0
void st_validate_state( struct st_context *st )
{
   struct st_state_flags *state = &st->dirty;
   GLuint i;

   /* Get Mesa driver state. */
   st->dirty.st |= st->ctx->NewDriverState;
   st->ctx->NewDriverState = 0;

   check_attrib_edgeflag(st);

   if (state->mesa)
      st_flush_bitmap_cache(st);

   check_program_state( st );

   st_manager_validate_framebuffers(st);

   if (state->st == 0)
      return;

   /*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/

#ifdef DEBUG
   if (1) {
#else
   if (0) {
#endif
      /* Debug version which enforces various sanity checks on the
       * state flags which are generated and checked to help ensure
       * state atoms are ordered correctly in the list.
       */
      struct st_state_flags examined, prev;      
      memset(&examined, 0, sizeof(examined));
      prev = *state;

      for (i = 0; i < ARRAY_SIZE(atoms); i++) {	 
	 const struct st_tracked_state *atom = atoms[i];
	 struct st_state_flags generated;
	 
	 /*printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st);*/

	 if (!(atom->dirty.mesa || atom->dirty.st) ||
	     !atom->update) {
	    printf("malformed atom %s\n", atom->name);
	    assert(0);
	 }

	 if (check_state(state, &atom->dirty)) {
	    atoms[i]->update( st );
	    /*printf("after: %x\n", atom->dirty.mesa);*/
	 }

	 accumulate_state(&examined, &atom->dirty);

	 /* generated = (prev ^ state)
	  * if (examined & generated)
	  *     fail;
	  */
	 xor_states(&generated, &prev, state);
	 assert(!check_state(&examined, &generated));
	 prev = *state;
      }
      /*printf("\n");*/

   }
   else {
      for (i = 0; i < ARRAY_SIZE(atoms); i++) {	 
	 if (check_state(state, &atoms[i]->dirty))
	    atoms[i]->update( st );
      }
   }

   memset(state, 0, sizeof(*state));
}
Esempio n. 13
0
/**
 * Called via ctx->Driver.DrawAtlasBitmap()
 */
static void
st_DrawAtlasBitmaps(struct gl_context *ctx,
                    const struct gl_bitmap_atlas *atlas,
                    GLuint count, const GLubyte *ids)
{
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
    struct st_texture_object *stObj = st_texture_object(atlas->texObj);
    struct pipe_sampler_view *sv;
    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
    const float z = ctx->Current.RasterPos[2] * 2.0f - 1.0f;
    const float *color = ctx->Current.RasterColor;
    const float clip_x_scale = 2.0f / st->state.framebuffer.width;
    const float clip_y_scale = 2.0f / st->state.framebuffer.height;
    const unsigned num_verts = count * 4;
    const unsigned num_vert_bytes = num_verts * sizeof(struct st_util_vertex);
    struct st_util_vertex *verts;
    struct pipe_vertex_buffer vb = {0};
    unsigned i;

    if (!st->bitmap.cache) {
        init_bitmap_state(st);
    }

    st_flush_bitmap_cache(st);

    st_validate_state(st, ST_PIPELINE_RENDER);
    st_invalidate_readpix_cache(st);

    sv = st_create_texture_sampler_view(pipe, stObj->pt);
    if (!sv) {
        _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)");
        return;
    }

    setup_render_state(ctx, sv, color, true);

    vb.stride = sizeof(struct st_util_vertex);

    u_upload_alloc(st->uploader, 0, num_vert_bytes, 4,
                   &vb.buffer_offset, &vb.buffer, (void **) &verts);

    /* build quads vertex data */
    for (i = 0; i < count; i++) {
        const GLfloat epsilon = 0.0001F;
        const struct gl_bitmap_glyph *g = &atlas->glyphs[ids[i]];
        const float xmove = g->xmove, ymove = g->ymove;
        const float xorig = g->xorig, yorig = g->yorig;
        const float s0 = g->x, t0 = g->y;
        const float s1 = s0 + g->w, t1 = t0 + g->h;
        const float x0 = IFLOOR(ctx->Current.RasterPos[0] - xorig + epsilon);
        const float y0 = IFLOOR(ctx->Current.RasterPos[1] - yorig + epsilon);
        const float x1 = x0 + g->w, y1 = y0 + g->h;
        const float clip_x0 = x0 * clip_x_scale - 1.0f;
        const float clip_y0 = y0 * clip_y_scale - 1.0f;
        const float clip_x1 = x1 * clip_x_scale - 1.0f;
        const float clip_y1 = y1 * clip_y_scale - 1.0f;

        /* lower-left corner */
        verts->x = clip_x0;
        verts->y = clip_y0;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s0;
        verts->t = t0;
        verts++;

        /* lower-right corner */
        verts->x = clip_x1;
        verts->y = clip_y0;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s1;
        verts->t = t0;
        verts++;

        /* upper-right corner */
        verts->x = clip_x1;
        verts->y = clip_y1;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s1;
        verts->t = t1;
        verts++;

        /* upper-left corner */
        verts->x = clip_x0;
        verts->y = clip_y1;
        verts->z = z;
        verts->r = color[0];
        verts->g = color[1];
        verts->b = color[2];
        verts->a = color[3];
        verts->s = s0;
        verts->t = t1;
        verts++;

        /* Update the raster position */
        ctx->Current.RasterPos[0] += xmove;
        ctx->Current.RasterPos[1] += ymove;
    }

    u_upload_unmap(st->uploader);

    cso_set_vertex_buffers(st->cso_context,
                           cso_get_aux_vertex_buffer_slot(st->cso_context),
                           1, &vb);

    cso_draw_arrays(st->cso_context, PIPE_PRIM_QUADS, 0, num_verts);

    restore_render_state(ctx);

    pipe_resource_reference(&vb.buffer, NULL);

    pipe_sampler_view_reference(&sv, NULL);

    /* We uploaded modified constants, need to invalidate them. */
    st->dirty |= ST_NEW_FS_CONSTANTS;
}
Esempio n. 14
0
/**
 * 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;
}
Esempio n. 15
0
/**
 * 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);
}
Esempio n. 16
0
static void
st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
           GLfloat width, GLfloat height)
{
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = st->pipe;
   struct cso_context *cso = st->cso_context;
   struct pipe_resource *vbuffer = NULL;
   GLuint i, numTexCoords, numAttribs;
   GLboolean emitColor;
   uint semantic_names[2 + MAX_TEXTURE_UNITS];
   uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
   struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS];
   unsigned offset;

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   st_validate_state(st, ST_PIPELINE_RENDER);

   /* determine if we need vertex color */
   if (ctx->FragmentProgram._Current->info.inputs_read & VARYING_BIT_COL0)
      emitColor = GL_TRUE;
   else
      emitColor = GL_FALSE;

   /* determine how many enabled sets of texcoords */
   numTexCoords = 0;
   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
      if (ctx->Texture.Unit[i]._Current &&
          ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
         numTexCoords++;
      }
   }

   /* total number of attributes per vertex */
   numAttribs = 1 + emitColor + numTexCoords;

   /* load vertex buffer */
   {
#define SET_ATTRIB(VERT, ATTR, X, Y, Z, W)                              \
      do {                                                              \
         GLuint k = (((VERT) * numAttribs + (ATTR)) * 4);               \
         assert(k < 4 * 4 * numAttribs);                                \
         vbuf[k + 0] = X;                                               \
         vbuf[k + 1] = Y;                                               \
         vbuf[k + 2] = Z;                                               \
         vbuf[k + 3] = W;                                               \
      } while (0)

      const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
      GLfloat *vbuf = NULL;
      GLuint tex_attr;

      u_upload_alloc(pipe->stream_uploader, 0,
                     numAttribs * 4 * 4 * sizeof(GLfloat), 4,
                     &offset, &vbuffer, (void **) &vbuf);
      if (!vbuffer) {
         return;
      }

      z = CLAMP(z, 0.0f, 1.0f);

      /* positions (in clip coords) */
      {
         const struct gl_framebuffer *fb = ctx->DrawBuffer;
         const GLfloat fb_width = (GLfloat)_mesa_geometric_width(fb);
         const GLfloat fb_height = (GLfloat)_mesa_geometric_height(fb);

         const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
         const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
         const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
         const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);

         SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f);   /* lower left */
         SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f);   /* lower right */
         SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f);   /* upper right */
         SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f);   /* upper left */

         semantic_names[0] = TGSI_SEMANTIC_POSITION;
         semantic_indexes[0] = 0;
      }

      /* colors */
      if (emitColor) {
         const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
         SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]);
         semantic_names[1] = TGSI_SEMANTIC_COLOR;
         semantic_indexes[1] = 0;
         tex_attr = 2;
      }
      else {
         tex_attr = 1;
      }

      /* texcoords */
      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
         if (ctx->Texture.Unit[i]._Current &&
             ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
            struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
            const struct gl_texture_image *img = _mesa_base_tex_image(obj);
            const GLfloat wt = (GLfloat) img->Width;
            const GLfloat ht = (GLfloat) img->Height;
            const GLfloat s0 = obj->CropRect[0] / wt;
            const GLfloat t0 = obj->CropRect[1] / ht;
            const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt;
            const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht;

            /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/
            SET_ATTRIB(0, tex_attr, s0, t0, 0.0f, 1.0f);  /* lower left */
            SET_ATTRIB(1, tex_attr, s1, t0, 0.0f, 1.0f);  /* lower right */
            SET_ATTRIB(2, tex_attr, s1, t1, 0.0f, 1.0f);  /* upper right */
            SET_ATTRIB(3, tex_attr, s0, t1, 0.0f, 1.0f);  /* upper left */

            semantic_names[tex_attr] = st->needs_texcoord_semantic ?
               TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
            /* XXX: should this use semantic index i instead of 0 ? */
            semantic_indexes[tex_attr] = 0;

            tex_attr++;
         }
      }

      u_upload_unmap(pipe->stream_uploader);

#undef SET_ATTRIB
   }

   cso_save_state(cso, (CSO_BIT_VIEWPORT |
                        CSO_BIT_STREAM_OUTPUTS |
                        CSO_BIT_VERTEX_SHADER |
                        CSO_BIT_TESSCTRL_SHADER |
                        CSO_BIT_TESSEVAL_SHADER |
                        CSO_BIT_GEOMETRY_SHADER |
                        CSO_BIT_VERTEX_ELEMENTS |
                        CSO_BIT_AUX_VERTEX_BUFFER_SLOT));

   {
      void *vs = lookup_shader(pipe, numAttribs,
                               semantic_names, semantic_indexes);
      cso_set_vertex_shader_handle(cso, vs);
   }
   cso_set_tessctrl_shader_handle(cso, NULL);
   cso_set_tesseval_shader_handle(cso, NULL);
   cso_set_geometry_shader_handle(cso, NULL);

   for (i = 0; i < numAttribs; i++) {
      velements[i].src_offset = i * 4 * sizeof(float);
      velements[i].instance_divisor = 0;
      velements[i].vertex_buffer_index = 0;
      velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
   }
   cso_set_vertex_elements(cso, numAttribs, velements);
   cso_set_stream_outputs(cso, 0, NULL, NULL);

   /* viewport state: viewport matching window dims */
   {
      const struct gl_framebuffer *fb = ctx->DrawBuffer;
      const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
      const GLfloat width = (GLfloat)_mesa_geometric_width(fb);
      const GLfloat height = (GLfloat)_mesa_geometric_height(fb);
      struct pipe_viewport_state vp;
      vp.scale[0] =  0.5f * width;
      vp.scale[1] = height * (invert ? -0.5f : 0.5f);
      vp.scale[2] = 1.0f;
      vp.translate[0] = 0.5f * width;
      vp.translate[1] = 0.5f * height;
      vp.translate[2] = 0.0f;
      cso_set_viewport(cso, &vp);
   }

   util_draw_vertex_buffer(pipe, cso, vbuffer,
			   cso_get_aux_vertex_buffer_slot(cso),
                           offset,  /* offset */
                           PIPE_PRIM_TRIANGLE_FAN,
                           4,  /* verts */
                           numAttribs); /* attribs/vert */

   pipe_resource_reference(&vbuffer, NULL);

   /* restore state */
   cso_restore_state(cso);
}
Esempio n. 17
0
/**
 * Called via ctx->Driver.GenerateMipmap().
 */
void
st_generate_mipmap(struct gl_context *ctx, GLenum target,
                   struct gl_texture_object *texObj)
{
   struct st_context *st = st_context(ctx);
   struct st_texture_object *stObj = st_texture_object(texObj);
   struct pipe_resource *pt = st_get_texobj_resource(texObj);
   const uint baseLevel = texObj->BaseLevel;
   enum pipe_format format;
   uint lastLevel, first_layer, last_layer;

   if (!pt)
      return;

   /* not sure if this ultimately actually should work,
      but we're not supporting multisampled textures yet. */
   assert(pt->nr_samples < 2);

   /* find expected last mipmap level to generate*/
   lastLevel = compute_num_levels(ctx, texObj, target) - 1;

   if (lastLevel == 0)
      return;

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   /* The texture isn't in a "complete" state yet so set the expected
    * lastLevel here, since it won't get done in st_finalize_texture().
    */
   stObj->lastLevel = lastLevel;

   if (!texObj->Immutable) {
      const GLboolean genSave = texObj->GenerateMipmap;

      /* Temporarily set GenerateMipmap to true so that allocate_full_mipmap()
       * makes the right decision about full mipmap allocation.
       */
      texObj->GenerateMipmap = GL_TRUE;

      _mesa_prepare_mipmap_levels(ctx, texObj, baseLevel, lastLevel);

      texObj->GenerateMipmap = genSave;

      /* At this point, memory for all the texture levels has been
       * allocated.  However, the base level image may be in one resource
       * while the subsequent/smaller levels may be in another resource.
       * Finalizing the texture will copy the base images from the former
       * resource to the latter.
       *
       * After this, we'll have all mipmap levels in one resource.
       */
      st_finalize_texture(ctx, st->pipe, texObj);
   }

   pt = stObj->pt;
   if (!pt) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "mipmap generation");
      return;
   }

   assert(pt->last_level >= lastLevel);

   if (pt->target == PIPE_TEXTURE_CUBE) {
      first_layer = last_layer = _mesa_tex_target_to_face(target);
   }
   else {
      first_layer = 0;
      last_layer = util_max_layer(pt, baseLevel);
   }

   if (stObj->surface_based)
      format = stObj->surface_format;
   else
      format = pt->format;

   /* First see if the driver supports hardware mipmap generation,
    * if not then generate the mipmap by rendering/texturing.
    * If that fails, use the software fallback.
    */
   if (!st->pipe->screen->get_param(st->pipe->screen,
                                    PIPE_CAP_GENERATE_MIPMAP) ||
       !st->pipe->generate_mipmap(st->pipe, pt, format, baseLevel,
                                  lastLevel, first_layer, last_layer)) {

      if (!util_gen_mipmap(st->pipe, pt, format, baseLevel, lastLevel,
                           first_layer, last_layer, PIPE_TEX_FILTER_LINEAR)) {
         _mesa_generate_mipmap(ctx, target, texObj);
      }
   }
}
Esempio n. 18
0
void st_validate_state( struct st_context *st )
{
    struct st_state_flags *state = &st->dirty;
    GLuint i;

    /* The bitmap cache is immune to pixel unpack changes.
     * Note that GLUT makes several calls to glPixelStore for each
     * bitmap char it draws so this is an important check.
     */
    if (state->mesa & ~_NEW_PACKUNPACK)
        st_flush_bitmap_cache(st);

    check_program_state( st );

    st_manager_validate_framebuffers(st);

    if (state->st == 0)
        return;

    /*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/

    if (1) {
        /* Debug version which enforces various sanity checks on the
         * state flags which are generated and checked to help ensure
         * state atoms are ordered correctly in the list.
         */
        struct st_state_flags examined, prev;
        memset(&examined, 0, sizeof(examined));
        prev = *state;

        for (i = 0; i < Elements(atoms); i++) {
            const struct st_tracked_state *atom = atoms[i];
            struct st_state_flags generated;

            /*printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st);*/

            if (!(atom->dirty.mesa || atom->dirty.st) ||
                    !atom->update) {
                printf("malformed atom %s\n", atom->name);
                assert(0);
            }

            if (check_state(state, &atom->dirty)) {
                atoms[i]->update( st );
                /*printf("after: %x\n", atom->dirty.mesa);*/
            }

            accumulate_state(&examined, &atom->dirty);

            /* generated = (prev ^ state)
             * if (examined & generated)
             *     fail;
             */
            xor_states(&generated, &prev, state);
            assert(!check_state(&examined, &generated));
            prev = *state;
        }
        /*printf("\n");*/

    }
    else {
        for (i = 0; i < Elements(atoms); i++) {
            if (check_state(state, &atoms[i]->dirty))
                atoms[i]->update( st );
        }
    }

    memset(state, 0, sizeof(*state));
}
Esempio n. 19
0
static void
st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct st_query_object *stq = st_query_object(q);
   unsigned type;
   bool ret = false;

   st_flush_bitmap_cache(st_context(ctx));

   /* convert GL query type to Gallium query type */
   switch (q->Target) {
   case GL_ANY_SAMPLES_PASSED:
   case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
      type = PIPE_QUERY_OCCLUSION_PREDICATE;
      break;
   case GL_SAMPLES_PASSED_ARB:
      type = PIPE_QUERY_OCCLUSION_COUNTER;
      break;
   case GL_PRIMITIVES_GENERATED:
      type = PIPE_QUERY_PRIMITIVES_GENERATED;
      break;
   case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
      type = PIPE_QUERY_PRIMITIVES_EMITTED;
      break;
   case GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB:
      type = PIPE_QUERY_SO_OVERFLOW_PREDICATE;
      break;
   case GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB:
      type = PIPE_QUERY_SO_OVERFLOW_PREDICATE;
      break;
   case GL_TIME_ELAPSED:
      if (st->has_time_elapsed)
         type = PIPE_QUERY_TIME_ELAPSED;
      else
         type = PIPE_QUERY_TIMESTAMP;
      break;
   case GL_VERTICES_SUBMITTED_ARB:
   case GL_PRIMITIVES_SUBMITTED_ARB:
   case GL_VERTEX_SHADER_INVOCATIONS_ARB:
   case GL_TESS_CONTROL_SHADER_PATCHES_ARB:
   case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB:
   case GL_GEOMETRY_SHADER_INVOCATIONS:
   case GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB:
   case GL_FRAGMENT_SHADER_INVOCATIONS_ARB:
   case GL_COMPUTE_SHADER_INVOCATIONS_ARB:
   case GL_CLIPPING_INPUT_PRIMITIVES_ARB:
   case GL_CLIPPING_OUTPUT_PRIMITIVES_ARB:
      type = PIPE_QUERY_PIPELINE_STATISTICS;
      break;
   default:
      assert(0 && "unexpected query target in st_BeginQuery()");
      return;
   }

   if (stq->type != type) {
      /* free old query of different type */
      free_queries(pipe, stq);
      stq->type = PIPE_QUERY_TYPES; /* an invalid value */
   }

   if (q->Target == GL_TIME_ELAPSED &&
       type == PIPE_QUERY_TIMESTAMP) {
      /* Determine time elapsed by emitting two timestamp queries. */
      if (!stq->pq_begin) {
         stq->pq_begin = pipe->create_query(pipe, type, 0);
         stq->type = type;
      }
      if (stq->pq_begin)
         ret = pipe->end_query(pipe, stq->pq_begin);
   } else {
      if (!stq->pq) {
         stq->pq = pipe->create_query(pipe, type, q->Stream);
         stq->type = type;
      }
      if (stq->pq)
         ret = pipe->begin_query(pipe, stq->pq);
   }

   if (!ret) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQuery");

      free_queries(pipe, stq);
      q->Active = GL_FALSE;
      return;
   }

   assert(stq->type == type);
}
Esempio n. 20
0
/**
 * Called via ctx->Driver.Clear()
 */
static void
st_Clear(struct gl_context *ctx, GLbitfield mask)
{
   struct st_context *st = st_context(ctx);
   struct gl_renderbuffer *depthRb
      = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
   struct gl_renderbuffer *stencilRb
      = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
   GLbitfield quad_buffers = 0x0;
   GLbitfield clear_buffers = 0x0;
   GLuint i;

   st_flush_bitmap_cache(st);

   /* This makes sure the pipe has the latest scissor, etc values */
   st_validate_state( st, ST_PIPELINE_RENDER );

   if (mask & BUFFER_BITS_COLOR) {
      for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
         GLint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];

         if (b >= 0 && mask & (1 << b)) {
            struct gl_renderbuffer *rb
               = ctx->DrawBuffer->Attachment[b].Renderbuffer;
            struct st_renderbuffer *strb = st_renderbuffer(rb);
            int colormask_index = ctx->Extensions.EXT_draw_buffers2 ? i : 0;

            if (!strb || !strb->surface)
               continue;

            if (is_color_disabled(ctx, colormask_index))
               continue;

            if (is_scissor_enabled(ctx, rb) ||
                is_color_masked(ctx, colormask_index))
               quad_buffers |= PIPE_CLEAR_COLOR0 << i;
            else
               clear_buffers |= PIPE_CLEAR_COLOR0 << i;
         }
      }
   }

   if (mask & BUFFER_BIT_DEPTH) {
      struct st_renderbuffer *strb = st_renderbuffer(depthRb);

      if (strb->surface && ctx->Depth.Mask) {
         if (is_scissor_enabled(ctx, depthRb))
            quad_buffers |= PIPE_CLEAR_DEPTH;
         else
            clear_buffers |= PIPE_CLEAR_DEPTH;
      }
   }
   if (mask & BUFFER_BIT_STENCIL) {
      struct st_renderbuffer *strb = st_renderbuffer(stencilRb);

      if (strb->surface && !is_stencil_disabled(ctx, stencilRb)) {
         if (is_scissor_enabled(ctx, stencilRb) ||
             is_stencil_masked(ctx, stencilRb))
            quad_buffers |= PIPE_CLEAR_STENCIL;
         else
            clear_buffers |= PIPE_CLEAR_STENCIL;
      }
   }

   /* Always clear depth and stencil together.
    * This can only happen when the stencil writemask is not a full mask.
    */
   if (quad_buffers & PIPE_CLEAR_DEPTHSTENCIL &&
       clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {
      quad_buffers |= clear_buffers & PIPE_CLEAR_DEPTHSTENCIL;
      clear_buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
   }

   /* Only use quad-based clearing for the renderbuffers which cannot
    * use pipe->clear. We want to always use pipe->clear for the other
    * renderbuffers, because it's likely to be faster.
    */
   if (quad_buffers) {
      clear_with_quad(ctx, quad_buffers);
   }
   if (clear_buffers) {
      /* We can't translate the clear color to the colorbuffer format,
       * because different colorbuffers may have different formats.
       */
      st->pipe->clear(st->pipe, clear_buffers,
                      (union pipe_color_union*)&ctx->Color.ClearColor,
                      ctx->Depth.Clear, ctx->Stencil.Clear);
   }
   if (mask & BUFFER_BIT_ACCUM)
      _mesa_clear_accum_buffer(ctx);
}
Esempio n. 21
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);
}
Esempio n. 22
0
/**
 * This function gets plugged into the VBO module and is called when
 * we have something to render.
 * Basically, translate the information into the format expected by gallium.
 */
void
st_draw_vbo(struct gl_context *ctx,
            const struct _mesa_prim *prims,
            GLuint nr_prims,
            const struct _mesa_index_buffer *ib,
	    GLboolean index_bounds_valid,
            GLuint min_index,
            GLuint max_index,
            struct gl_transform_feedback_object *tfb_vertcount,
            unsigned stream,
            struct gl_buffer_object *indirect)
{
   struct st_context *st = st_context(ctx);
   struct pipe_index_buffer ibuffer = {0};
   struct pipe_draw_info info;
   const struct gl_vertex_array **arrays = ctx->Array._DrawArrays;
   unsigned i;

   /* Mesa core state should have been validated already */
   assert(ctx->NewState == 0x0);

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   /* Validate state. */
   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK ||
       st->gfx_shaders_may_be_dirty) {
      st_validate_state(st, ST_PIPELINE_RENDER);
   }

   if (st->vertex_array_out_of_memory) {
      return;
   }

   util_draw_init_info(&info);

   if (ib) {
      /* Get index bounds for user buffers. */
      if (!index_bounds_valid)
         if (!all_varyings_in_vbos(arrays))
            vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
                                   nr_prims);

      if (!setup_index_buffer(st, ib, &ibuffer)) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBegin/DrawElements/DrawArray");
         return;
      }

      info.indexed = TRUE;
      if (min_index != ~0U && max_index != ~0U) {
         info.min_index = min_index;
         info.max_index = max_index;
      }

      /* The VBO module handles restart for the non-indexed GLDrawArrays
       * so we only set these fields for indexed drawing:
       */
      setup_primitive_restart(ctx, ib, &info);
   }
   else {
      /* Transform feedback drawing is always non-indexed. */
      /* Set info.count_from_stream_output. */
      if (tfb_vertcount) {
         if (!st_transform_feedback_draw_init(tfb_vertcount, stream, &info))
            return;
      }
   }

   assert(!indirect);

   /* do actual drawing */
   for (i = 0; i < nr_prims; i++) {
      info.mode = translate_prim(ctx, prims[i].mode);
      info.start = prims[i].start;
      info.count = prims[i].count;
      info.start_instance = prims[i].base_instance;
      info.instance_count = prims[i].num_instances;
      info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
      info.index_bias = prims[i].basevertex;
      info.drawid = prims[i].draw_id;
      if (!ib) {
         info.min_index = info.start;
         info.max_index = info.start + info.count - 1;
      }

      if (ST_DEBUG & DEBUG_DRAW) {
         debug_printf("st/draw: mode %s  start %u  count %u  indexed %d\n",
                      u_prim_name(info.mode),
                      info.start,
                      info.count,
                      info.indexed);
      }

      if (info.count_from_stream_output) {
         cso_draw_vbo(st->cso_context, &info);
      }
      else if (info.primitive_restart) {
         /* don't trim, restarts might be inside index list */
         cso_draw_vbo(st->cso_context, &info);
      }
      else if (u_trim_pipe_prim(prims[i].mode, &info.count)) {
         cso_draw_vbo(st->cso_context, &info);
      }
   }

   if (ib && st->indexbuf_uploader && !_mesa_is_bufferobj(ib->obj)) {
      pipe_resource_reference(&ibuffer.buffer, NULL);
   }
}