Пример #1
0
static void
fallback_generate_mipmap(GLcontext *ctx, GLenum target,
                         struct gl_texture_object *texObj)
{
   struct pipe_context *pipe = ctx->st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_texture *pt = st_get_texobj_texture(texObj);
   const uint baseLevel = texObj->BaseLevel;
   const uint lastLevel = pt->last_level;
   const uint face = _mesa_tex_target_to_face(target), zslice = 0;
   uint dstLevel;
   GLenum datatype;
   GLuint comps;

   assert(target != GL_TEXTURE_3D); /* not done yet */

   _mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
                                  &datatype, &comps);

   for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
      const uint srcLevel = dstLevel - 1;
      struct pipe_transfer *srcTrans, *dstTrans;
      const ubyte *srcData;
      ubyte *dstData;
      int srcStride, dstStride;

      srcTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face,
						srcLevel, zslice,
						PIPE_TRANSFER_READ, 0, 0,
						pt->width[srcLevel],
						pt->height[srcLevel]);

      dstTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face,
						dstLevel, zslice,
						PIPE_TRANSFER_WRITE, 0, 0,
						pt->width[dstLevel],
						pt->height[dstLevel]);

      srcData = (ubyte *) screen->transfer_map(screen, srcTrans);
      dstData = (ubyte *) screen->transfer_map(screen, dstTrans);

      srcStride = srcTrans->stride / srcTrans->block.size;
      dstStride = dstTrans->stride / dstTrans->block.size;

      _mesa_generate_mipmap_level(target, datatype, comps,
                   0 /*border*/,
                   pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel],
                   srcData,
                   srcStride, /* stride in texels */
                   pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel],
                   dstData,
                   dstStride); /* stride in texels */

      screen->transfer_unmap(screen, srcTrans);
      screen->transfer_unmap(screen, dstTrans);

      screen->tex_transfer_destroy(srcTrans);
      screen->tex_transfer_destroy(dstTrans);
   }
}
Пример #2
0
static void
accum_load(struct st_context *st, GLfloat value,
           GLint xpos, GLint ypos, GLint width, GLint height,
           struct st_renderbuffer *acc_strb,
           struct st_renderbuffer *color_strb)
{
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_transfer *color_trans;
   size_t stride = acc_strb->stride;
   GLubyte *data = acc_strb->data;
   GLfloat *buf;


   if (ST_DEBUG & DEBUG_FALLBACK)
      debug_printf("%s: fallback processing\n", __FUNCTION__);

   color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture,
						0, 0, 0,
						PIPE_TRANSFER_READ, xpos, ypos,
						width, height);

   buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));

   pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf);

   switch (acc_strb->format) {
   case PIPE_FORMAT_R16G16B16A16_SNORM:
      {
         const GLfloat *color = buf;
         int i, j;
         for (i = 0; i < height; i++) {
            GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
            for (j = 0; j < width * 4; j++) {
               float val = *color++ * value;
               *acc++ = FLOAT_TO_SHORT(val);
            }
         }
      }
      break;
   default:
      _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
   }

   _mesa_free(buf);
   screen->tex_transfer_destroy(color_trans);
}
Пример #3
0
/**
 * Update the pixelmap texture with the contents of the R/G/B/A pixel maps.
 */
static void
load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt)
{
   struct pipe_context *pipe = ctx->st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_transfer *transfer;
   const GLuint rSize = ctx->PixelMaps.RtoR.Size;
   const GLuint gSize = ctx->PixelMaps.GtoG.Size;
   const GLuint bSize = ctx->PixelMaps.BtoB.Size;
   const GLuint aSize = ctx->PixelMaps.AtoA.Size;
   const uint texSize = pt->width[0];
   uint *dest;
   uint i, j;

   transfer = st_cond_flush_get_tex_transfer(st_context(ctx),
					     pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
					     0, 0, texSize, texSize);
   dest = (uint *) screen->transfer_map(screen, transfer);

   /* Pack four 1D maps into a 2D texture:
    * R map is placed horizontally, indexed by S, in channel 0
    * G map is placed vertically, indexed by T, in channel 1
    * B map is placed horizontally, indexed by S, in channel 2
    * A map is placed vertically, indexed by T, in channel 3
    */
   for (i = 0; i < texSize; i++) {
      for (j = 0; j < texSize; j++) {
         int k = (i * texSize + j);
         ubyte r = ctx->PixelMaps.RtoR.Map8[j * rSize / texSize];
         ubyte g = ctx->PixelMaps.GtoG.Map8[i * gSize / texSize];
         ubyte b = ctx->PixelMaps.BtoB.Map8[j * bSize / texSize];
         ubyte a = ctx->PixelMaps.AtoA.Map8[i * aSize / texSize];
         util_pack_color_ub(r, g, b, a, pt->format, dest + k);
      }
   }

   screen->transfer_unmap(screen, transfer);
   screen->tex_transfer_destroy(transfer);
}
Пример #4
0
static void
accum_return(GLcontext *ctx, GLfloat value,
             GLint xpos, GLint ypos, GLint width, GLint height,
             struct st_renderbuffer *acc_strb,
             struct st_renderbuffer *color_strb)
{
   struct pipe_context *pipe = ctx->st->pipe;
   struct pipe_screen *screen = pipe->screen;
   const GLubyte *colormask = ctx->Color.ColorMask;
   enum pipe_transfer_usage usage;
   struct pipe_transfer *color_trans;
   size_t stride = acc_strb->stride;
   const GLubyte *data = acc_strb->data;
   GLfloat *buf;

   if (ST_DEBUG & DEBUG_FALLBACK)
      debug_printf("%s: fallback processing\n", __FUNCTION__);

   buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));

   if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3])
      usage = PIPE_TRANSFER_READ_WRITE;
   else
      usage = PIPE_TRANSFER_WRITE;
   
   color_trans = st_cond_flush_get_tex_transfer(st_context(ctx),
						color_strb->texture, 0, 0, 0,
						usage,
						xpos, ypos,
						width, height);

   if (usage & PIPE_TRANSFER_READ)
      pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf);

   switch (acc_strb->format) {
   case PIPE_FORMAT_R16G16B16A16_SNORM:
      {
         GLfloat *color = buf;
         int i, j, ch;
         for (i = 0; i < height; i++) {
            const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8);
            for (j = 0; j < width; j++) {
               for (ch = 0; ch < 4; ch++) {
                  if (colormask[ch]) {
                     GLfloat val = SHORT_TO_FLOAT(*acc * value);
                     *color = CLAMP(val, 0.0f, 1.0f);
                  }
                  else {
                     /* No change */
                  }
                  ++acc;
                  ++color;
               }
            }
         }
      }
      break;
   default:
      _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
   }

   pipe_put_tile_rgba(color_trans, 0, 0, width, height, buf);

   _mesa_free(buf);
   screen->tex_transfer_destroy(color_trans);
}
Пример #5
0
static void
st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
              GLsizei width, GLsizei height,
              GLint dstx, GLint dsty, GLenum type)
{
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct st_renderbuffer *rbRead;
   struct st_vertex_program *stvp;
   struct st_fragment_program *stfp;
   struct pipe_texture *pt;
   GLfloat *color;
   enum pipe_format srcFormat, texFormat;

   pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);

   st_validate_state(st);

   if (srcx < 0) {
      width -= -srcx;
      dstx += -srcx;
      srcx = 0;
   }

   if (srcy < 0) {
      height -= -srcy;
      dsty += -srcy;
      srcy = 0;
   }

   if (dstx < 0) {
      width -= -dstx;
      srcx += -dstx;
      dstx = 0;
   }

   if (dsty < 0) {
      height -= -dsty;
      srcy += -dsty;
      dsty = 0;
   }

   if (width < 0 || height < 0)
      return;


   if (type == GL_STENCIL) {
      /* can't use texturing to do stencil */
      copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
      return;
   }

   if (type == GL_COLOR) {
      rbRead = st_get_color_read_renderbuffer(ctx);
      color = NULL;
      stfp = combined_drawpix_fragment_program(ctx);
      stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
   }
   else {
      assert(type == GL_DEPTH);
      rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
      color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
      stfp = make_fragment_shader_z(ctx->st);
      stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
   }

   srcFormat = rbRead->texture->format;

   if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D, 
                                   PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
      texFormat = srcFormat;
   }
   else {
      /* srcFormat can't be used as a texture format */
      if (type == GL_DEPTH) {
         texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, 
                                      PIPE_TEXTURE_USAGE_DEPTH_STENCIL);
         assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */
      }
      else {
         /* default color format */
         texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, 
                                      PIPE_TEXTURE_USAGE_SAMPLER);
         assert(texFormat != PIPE_FORMAT_NONE);
      }
   }

   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
      srcy = ctx->DrawBuffer->Height - srcy - height;

      if (srcy < 0) {
         height -= -srcy;
         srcy = 0;
      }
      
      if (height < 0)
         return;
   }

   pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0,
                          width, height, 1,
                          PIPE_TEXTURE_USAGE_SAMPLER);
   if (!pt)
      return;


   if (srcFormat == texFormat) {
      /* copy source framebuffer surface into mipmap/texture */
      struct pipe_surface *psRead = screen->get_tex_surface(screen,
                                       rbRead->texture, 0, 0, 0,
                                       PIPE_BUFFER_USAGE_GPU_READ);
      struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, 
                                      PIPE_BUFFER_USAGE_GPU_WRITE );
      pipe->surface_copy(pipe,
			 psTex, /* dest */
			 0, 0, /* destx/y */
			 psRead,
			 srcx, srcy, width, height);
      pipe_surface_reference(&psRead, NULL); 
      pipe_surface_reference(&psTex, NULL);
   }
   else {
      /* CPU-based fallback/conversion */
      struct pipe_transfer *ptRead =
         st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0,
					PIPE_TRANSFER_READ, srcx, srcy, width,
					height);
      struct pipe_transfer *ptTex;
      enum pipe_transfer_usage transfer_usage;

      if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format))
         transfer_usage = PIPE_TRANSFER_READ_WRITE;
      else
         transfer_usage = PIPE_TRANSFER_WRITE;

      ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage,
                                             0, 0, width, height);

      if (type == GL_COLOR) {
         /* alternate path using get/put_tile() */
         GLfloat *buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));

         pipe_get_tile_rgba(ptRead, 0, 0, width, height, buf);
         pipe_put_tile_rgba(ptTex, 0, 0, width, height, buf);

         _mesa_free(buf);
      }
      else {
         /* GL_DEPTH */
         GLuint *buf = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
         pipe_get_tile_z(ptRead, 0, 0, width, height, buf);
         pipe_put_tile_z(ptTex, 0, 0, width, height, buf);
         _mesa_free(buf);
      }

      screen->tex_transfer_destroy(ptRead);
      screen->tex_transfer_destroy(ptTex);
   }

   /* draw textured quad */
   draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
                      width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
                      pt, stvp, stfp, color, GL_TRUE);

   pipe_texture_reference(&pt, NULL);
}
Пример #6
0
static void
copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
                    GLsizei width, GLsizei height,
                    GLint dstx, GLint dsty)
{
   struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
   struct pipe_screen *screen = ctx->st->pipe->screen;
   enum pipe_transfer_usage usage;
   struct pipe_transfer *ptDraw;
   ubyte *drawMap;
   ubyte *buffer;
   int i;

   buffer = _mesa_malloc(width * height * sizeof(ubyte));
   if (!buffer) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
      return;
   }

   /* this will do stencil pixel transfer ops */
   st_read_stencil_pixels(ctx, srcx, srcy, width, height,
                          GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
                          &ctx->DefaultPacking, buffer);

   if(pf_get_component_bits( rbDraw->format, PIPE_FORMAT_COMP_Z ) != 0)
      usage = PIPE_TRANSFER_READ_WRITE;
   else
      usage = PIPE_TRANSFER_WRITE;
   
   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
      dsty = rbDraw->Base.Height - dsty - height;
   }

   ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx),
					   rbDraw->texture, 0, 0, 0,
					   usage, dstx, dsty,
					   width, height);

   assert(ptDraw->block.width == 1);
   assert(ptDraw->block.height == 1);
   
   /* map the stencil buffer */
   drawMap = screen->transfer_map(screen, ptDraw);

   /* draw */
   /* XXX PixelZoom not handled yet */
   for (i = 0; i < height; i++) {
      ubyte *dst;
      const ubyte *src;
      int y;

      y = i;

      if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
         y = height - y - 1;
      }

      dst = drawMap + y * ptDraw->stride;
      src = buffer + i * width;

      switch (ptDraw->format) {
      case PIPE_FORMAT_S8Z24_UNORM:
         {
            uint *dst4 = (uint *) dst;
            int j;
            assert(usage == PIPE_TRANSFER_READ_WRITE);
            for (j = 0; j < width; j++) {
               *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
               dst4++;
            }
         }
         break;
      case PIPE_FORMAT_Z24S8_UNORM:
         {
            uint *dst4 = (uint *) dst;
            int j;
            assert(usage == PIPE_TRANSFER_READ_WRITE);
            for (j = 0; j < width; j++) {
               *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff);
               dst4++;
            }
         }
         break;
      case PIPE_FORMAT_S8_UNORM:
         assert(usage == PIPE_TRANSFER_WRITE);
         memcpy(dst, src, width);
         break;
      default:
         assert(0);
      }
   }

   _mesa_free(buffer);

   /* unmap the stencil buffer */
   screen->transfer_unmap(screen, ptDraw);
   screen->tex_transfer_destroy(ptDraw);
}
Пример #7
0
static void
draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
                    GLsizei width, GLsizei height, GLenum format, GLenum type,
                    const struct gl_pixelstore_attrib *unpack,
                    const GLvoid *pixels)
{
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct st_renderbuffer *strb;
   enum pipe_transfer_usage usage;
   struct pipe_transfer *pt;
   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
   GLint skipPixels;
   ubyte *stmap;

   strb = st_renderbuffer(ctx->DrawBuffer->
                          Attachment[BUFFER_STENCIL].Renderbuffer);

   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
      y = ctx->DrawBuffer->Height - y - height;
   }

   if(format != GL_DEPTH_STENCIL && 
      pf_get_component_bits( strb->format, PIPE_FORMAT_COMP_Z ) != 0)
      usage = PIPE_TRANSFER_READ_WRITE;
   else
      usage = PIPE_TRANSFER_WRITE;
   
   pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0,
				       usage, x, y,
				       width, height);

   stmap = screen->transfer_map(screen, pt);

   pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels);
   assert(pixels);

   /* if width > MAX_WIDTH, have to process image in chunks */
   skipPixels = 0;
   while (skipPixels < width) {
      const GLint spanX = skipPixels;
      const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
      GLint row;
      for (row = 0; row < height; row++) {
         GLubyte sValues[MAX_WIDTH];
         GLuint zValues[MAX_WIDTH];
         GLenum destType = GL_UNSIGNED_BYTE;
         const GLvoid *source = _mesa_image_address2d(unpack, pixels,
                                                      width, height,
                                                      format, type,
                                                      row, skipPixels);
         _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues,
                                   type, source, unpack,
                                   ctx->_ImageTransferState);

         if (format == GL_DEPTH_STENCIL) {
            _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues,
                                    (1 << 24) - 1, type, source, unpack);
         }

         if (zoom) {
            _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
                          "zoom not complete");
         }

         {
            GLint spanY;

            if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
               spanY = height - row - 1;
            }
            else {
               spanY = row;
            }

            /* now pack the stencil (and Z) values in the dest format */
            switch (pt->format) {
            case PIPE_FORMAT_S8_UNORM:
               {
                  ubyte *dest = stmap + spanY * pt->stride + spanX;
                  assert(usage == PIPE_TRANSFER_WRITE);
                  memcpy(dest, sValues, spanWidth);
               }
               break;
            case PIPE_FORMAT_S8Z24_UNORM:
               if (format == GL_DEPTH_STENCIL) {
                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
                  GLint k;
                  assert(usage == PIPE_TRANSFER_WRITE);
                  for (k = 0; k < spanWidth; k++) {
                     dest[k] = zValues[k] | (sValues[k] << 24);
                  }
               }
               else {
                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
                  GLint k;
                  assert(usage == PIPE_TRANSFER_READ_WRITE);
                  for (k = 0; k < spanWidth; k++) {
                     dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
                  }
               }
               break;
            case PIPE_FORMAT_Z24S8_UNORM:
               if (format == GL_DEPTH_STENCIL) {
                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
                  GLint k;
                  assert(usage == PIPE_TRANSFER_WRITE);
                  for (k = 0; k < spanWidth; k++) {
                     dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
                  }
               }
               else {
                  uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
                  GLint k;
                  assert(usage == PIPE_TRANSFER_READ_WRITE);
                  for (k = 0; k < spanWidth; k++) {
                     dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
                  }
               }
               break;
            default:
               assert(0);
            }
         }
      }
      skipPixels += spanWidth;
   }

   _mesa_unmap_drawpix_pbo(ctx, unpack);

   /* unmap the stencil buffer */
   screen->transfer_unmap(screen, pt);
   screen->tex_transfer_destroy(pt);
}