예제 #1
0
static void
slow_read_rgba_pixels( struct gl_context *ctx,
		       GLint x, GLint y,
		       GLsizei width, GLsizei height,
		       GLenum format, GLenum type,
		       GLvoid *pixels,
		       const struct gl_pixelstore_attrib *packing,
		       GLbitfield transferOps )
{
   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
   const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format);
   void *rgba;
   GLubyte *dst, *map;
   int dstStride, stride, j;

   dstStride = _mesa_image_row_stride(packing, width, format, type);
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
					   format, type, 0, 0);

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
			       &map, &stride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return;
   }

   rgba = malloc(width * MAX_PIXEL_BYTES);
   if (!rgba)
      goto done;

   for (j = 0; j < height; j++) {
      if (_mesa_is_integer_format(format)) {
	 _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba);
	 _mesa_pack_rgba_span_int(ctx, width, (GLuint (*)[4]) rgba, format,
                                  type, dst);
      } else {
	 _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba);
	 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
                                    type, dst, packing, transferOps);
      }
      dst += dstStride;
      map += stride;
   }

   free(rgba);

done:
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
예제 #2
0
/**
 * glGetTexImagefor sRGB pixels;
 */
static void
get_tex_srgb(GLcontext *ctx, GLuint dimensions,
             GLenum format, GLenum type, GLvoid *pixels,
             const struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   const GLbitfield transferOps = 0x0;
   GLint img, row;

   for (img = 0; img < depth; img++) {
      for (row = 0; row < height; row++) {
         void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                          width, height, format, type,
                                          img, row, 0);

         GLfloat rgba[MAX_WIDTH][4];
         GLint col;

         /* convert row to RGBA format */
         for (col = 0; col < width; col++) {
            texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
            if (texImage->_BaseFormat == GL_LUMINANCE) {
               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
               rgba[col][GCOMP] = 0.0;
               rgba[col][BCOMP] = 0.0;
            }
            else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
               rgba[col][GCOMP] = 0.0;
               rgba[col][BCOMP] = 0.0;
            }
            else if (texImage->_BaseFormat == GL_RGB ||
                     texImage->_BaseFormat == GL_RGBA) {
               rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
               rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
               rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
            }
         }
         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                    format, type, dest,
                                    &ctx->Pack, transferOps);
      }
   }
}
예제 #3
0
static void GLAPIENTRY
_mesa_GetColorTable( GLenum target, GLenum format,
                     GLenum type, GLvoid *data )
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
   struct gl_color_table *table = NULL;
   GLfloat rgba[MAX_COLOR_TABLE_SIZE][4];
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

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

   switch (target) {
      case GL_SHARED_TEXTURE_PALETTE_EXT:
         table = &ctx->Texture.Palette;
         break;
      case GL_COLOR_TABLE:
         table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
         break;
      case GL_TEXTURE_COLOR_TABLE_SGI:
         if (!ctx->Extensions.SGI_texture_color_table) {
            _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
            return;
         }
         table = &(texUnit->ColorTable);
         break;
      case GL_POST_CONVOLUTION_COLOR_TABLE:
         table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
         break;
      case GL_POST_COLOR_MATRIX_COLOR_TABLE:
         table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
         break;
      default:
         /* try texture targets */
         {
            struct gl_texture_object *texobj
               = _mesa_select_tex_object(ctx, texUnit, target);
            if (texobj && !_mesa_is_proxy_texture(target)) {
               table = &texobj->Palette;
            }
            else {
               _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
               return;
            }
         }
   }

   ASSERT(table);

   if (table->Size <= 0) {
      return;
   }

   switch (table->_BaseFormat) {
   case GL_ALPHA:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] = 0;
            rgba[i][GCOMP] = 0;
            rgba[i][BCOMP] = 0;
            rgba[i][ACOMP] = table->TableF[i];
         }
      }
      break;
   case GL_LUMINANCE:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] = table->TableF[i];
            rgba[i][ACOMP] = 1.0F;
         }
      }
      break;
   case GL_LUMINANCE_ALPHA:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] = table->TableF[i*2+0];
            rgba[i][ACOMP] = table->TableF[i*2+1];
         }
      }
      break;
   case GL_INTENSITY:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] =
            rgba[i][ACOMP] = table->TableF[i];
         }
      }
      break;
   case GL_RGB:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] = table->TableF[i*3+0];
            rgba[i][GCOMP] = table->TableF[i*3+1];
            rgba[i][BCOMP] = table->TableF[i*3+2];
            rgba[i][ACOMP] = 1.0F;
         }
      }
      break;
   case GL_RGBA:
      _mesa_memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat));
      break;
   default:
      _mesa_problem(ctx, "bad table format in glGetColorTable");
      return;
   }

   data = _mesa_map_validate_pbo_dest(ctx, 
                                      1, &ctx->Pack, table->Size, 1, 1,
                                      format, type, data,
                                      "glGetColorTable");
   if (!data)
      return;

   _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
                              format, type, data, &ctx->Pack, 0x0);

   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
예제 #4
0
파일: colortab.c 프로젝트: nikai3d/mesa
static void GLAPIENTRY
_mesa_GetnColorTableARB( GLenum target, GLenum format, GLenum type,
                         GLsizei bufSize, GLvoid *data )
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
   struct gl_color_table *table = NULL;
   GLfloat rgba[MAX_COLOR_TABLE_SIZE][4];
   GLbitfield transferOps = 0;
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

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

   switch (target) {
      case GL_SHARED_TEXTURE_PALETTE_EXT:
         table = &ctx->Texture.Palette;
         break;
      default:
         /* try texture targets */
         {
            struct gl_texture_object *texobj
               = _mesa_select_tex_object(ctx, texUnit, target);
            if (texobj && !_mesa_is_proxy_texture(target)) {
               table = &texobj->Palette;
            }
            else {
               _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
               return;
            }
         }
   }

   ASSERT(table);

   if (table->Size <= 0) {
      return;
   }

   switch (table->_BaseFormat) {
   case GL_ALPHA:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] = 0;
            rgba[i][GCOMP] = 0;
            rgba[i][BCOMP] = 0;
            rgba[i][ACOMP] = table->TableF[i];
         }
      }
      break;
   case GL_LUMINANCE:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] = table->TableF[i];
            rgba[i][ACOMP] = 1.0F;
         }
      }
      break;
   case GL_LUMINANCE_ALPHA:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] = table->TableF[i*2+0];
            rgba[i][ACOMP] = table->TableF[i*2+1];
         }
      }
      break;
   case GL_INTENSITY:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] =
            rgba[i][ACOMP] = table->TableF[i];
         }
      }
      break;
   case GL_RGB:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] = table->TableF[i*3+0];
            rgba[i][GCOMP] = table->TableF[i*3+1];
            rgba[i][BCOMP] = table->TableF[i*3+2];
            rgba[i][ACOMP] = 1.0F;
         }
      }
      break;
   case GL_RGBA:
      memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat));
      break;
   default:
      _mesa_problem(ctx, "bad table format in glGetColorTable");
      return;
   }

   data = _mesa_map_validate_pbo_dest(ctx, 
                                      1, &ctx->Pack, table->Size, 1, 1,
                                      format, type, bufSize, data,
                                      "glGetColorTable");
   if (!data)
      return;

   /* TODO: is this correct? */
   if(ctx->Color._ClampReadColor)
      transferOps |= IMAGE_CLAMP_BIT;

   _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
                              format, type, data, &ctx->Pack, transferOps);

   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
}
예제 #5
0
/**
 * glGetTexImage() helper: decompress a compressed texture by rendering
 * a textured quad.  Store the results in the user's buffer.
 */
static void
decompress_with_blit(struct gl_context * ctx,
                     GLenum format, GLenum type, GLvoid *pixels,
                     struct gl_texture_image *texImage)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct st_texture_image *stImage = st_texture_image(texImage);
   struct st_texture_object *stObj = st_texture_object(texImage->TexObject);
   const GLuint width = texImage->Width;
   const GLuint height = texImage->Height;
   struct pipe_resource *dst_texture;
   struct pipe_blit_info blit;
   unsigned bind = (PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_READ);
   struct pipe_transfer *tex_xfer;
   ubyte *map;

   /* create temp / dest surface */
   if (!util_create_rgba_texture(pipe, width, height, bind,
                                 &dst_texture)) {
      _mesa_problem(ctx, "util_create_rgba_texture() failed "
                    "in decompress_with_blit()");
      return;
   }

   blit.src.resource = stObj->pt;
   blit.src.level = texImage->Level;
   blit.src.format = util_format_linear(stObj->pt->format);
   blit.dst.resource = dst_texture;
   blit.dst.level = 0;
   blit.dst.format = dst_texture->format;
   blit.src.box.x = blit.dst.box.x = 0;
   blit.src.box.y = blit.dst.box.y = 0;
   blit.src.box.z = 0; /* XXX compressed array textures? */
   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 = PIPE_MASK_RGBA;
   blit.filter = PIPE_TEX_FILTER_NEAREST;
   blit.scissor_enable = FALSE;

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

   pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels);

   map = pipe_transfer_map(pipe, dst_texture, 0, 0,
                           PIPE_TRANSFER_READ,
                           0, 0, width, height, &tex_xfer);
   if (!map) {
      goto end;
   }

   /* copy/pack data into user buffer */
   if (_mesa_format_matches_format_and_type(stImage->base.TexFormat,
                                            format, type,
                                            ctx->Pack.SwapBytes)) {
      /* memcpy */
      const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format);
      /* map the dst_surface so we can read from it */
      GLuint row;
      for (row = 0; row < height; row++) {
         GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
                                              height, format, type, row, 0);
         memcpy(dest, map, bytesPerRow);
         map += tex_xfer->stride;
      }
      pipe_transfer_unmap(pipe, tex_xfer);
   }
   else {
      /* format translation via floats */
      GLuint row;
      enum pipe_format pformat = util_format_linear(dst_texture->format);
      GLfloat *rgba;

      rgba = malloc(width * 4 * sizeof(GLfloat));
      if (!rgba) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
         goto end;
      }

      for (row = 0; row < height; row++) {
         const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
         GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
                                              height, format, type, row, 0);

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

         /* get float[4] rgba row from surface */
         pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1,
                                   pformat, rgba);

         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
                                    type, dest, &ctx->Pack, transferOps);
      }

      free(rgba);
   }

end:
   if (map)
      pipe_transfer_unmap(pipe, tex_xfer);

   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
   pipe_resource_reference(&dst_texture, NULL);
}
예제 #6
0
/**
 * glGetTexImage() helper: decompress a compressed texture by rendering
 * a textured quad.  Store the results in the user's buffer.
 */
static void
decompress_with_blit(struct gl_context * ctx,
                     GLenum format, GLenum type, GLvoid *pixels,
                     struct gl_texture_image *texImage)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct st_texture_image *stImage = st_texture_image(texImage);
   struct st_texture_object *stObj = st_texture_object(texImage->TexObject);
   struct pipe_sampler_view *src_view;
   const GLuint width = texImage->Width;
   const GLuint height = texImage->Height;
   struct pipe_surface *dst_surface;
   struct pipe_resource *dst_texture;
   struct pipe_transfer *tex_xfer;
   unsigned bind = (PIPE_BIND_RENDER_TARGET | /* util_blit may choose to render */
		    PIPE_BIND_TRANSFER_READ);

   /* create temp / dest surface */
   if (!util_create_rgba_surface(pipe, width, height, bind,
                                 &dst_texture, &dst_surface)) {
      _mesa_problem(ctx, "util_create_rgba_surface() failed "
                    "in decompress_with_blit()");
      return;
   }

   /* Disable conditional rendering. */
   if (st->render_condition) {
      pipe->render_condition(pipe, NULL, 0);
   }

   /* Create sampler view that limits fetches to the source mipmap level */
   {
      struct pipe_sampler_view sv_temp;

      u_sampler_view_default_template(&sv_temp, stObj->pt, stObj->pt->format);

      sv_temp.format = util_format_linear(sv_temp.format);
      sv_temp.u.tex.first_level =
      sv_temp.u.tex.last_level = texImage->Level;

      src_view = pipe->create_sampler_view(pipe, stObj->pt, &sv_temp);
      if (!src_view) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         return;
      }
   }

   /* blit/render/decompress */
   util_blit_pixels_tex(st->blit,
                        src_view,      /* pipe_resource (src) */
                        0, 0,             /* src x0, y0 */
                        width, height,    /* src x1, y1 */
                        dst_surface,      /* pipe_surface (dst) */
                        0, 0,             /* dst x0, y0 */
                        width, height,    /* dst x1, y1 */
                        0.0,              /* z */
                        PIPE_TEX_MIPFILTER_NEAREST);

   /* Restore conditional rendering state. */
   if (st->render_condition) {
      pipe->render_condition(pipe, st->render_condition,
                             st->condition_mode);
   }

   /* map the dst_surface so we can read from it */
   tex_xfer = pipe_get_transfer(pipe,
                                dst_texture, 0, 0,
                                PIPE_TRANSFER_READ,
                                0, 0, width, height);

   pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels);

   /* copy/pack data into user buffer */
   if (_mesa_format_matches_format_and_type(stImage->base.TexFormat,
                                            format, type,
                                            ctx->Pack.SwapBytes)) {
      /* memcpy */
      const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format);
      ubyte *map = pipe_transfer_map(pipe, tex_xfer);
      GLuint row;
      for (row = 0; row < height; row++) {
         GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
                                              height, format, type, row, 0);
         memcpy(dest, map, bytesPerRow);
         map += tex_xfer->stride;
      }
      pipe_transfer_unmap(pipe, tex_xfer);
   }
   else {
      /* format translation via floats */
      GLuint row;
      enum pipe_format pformat = util_format_linear(dst_texture->format);
      GLfloat *rgba;

      rgba = (GLfloat *) malloc(width * 4 * sizeof(GLfloat));
      if (!rgba) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
         goto end;
      }

      for (row = 0; row < height; row++) {
         const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
         GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
                                              height, format, type, row, 0);

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

         /* get float[4] rgba row from surface */
         pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1,
                                   pformat, rgba);

         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
                                    type, dest, &ctx->Pack, transferOps);
      }

      free(rgba);
   }

end:
   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);

   pipe->transfer_destroy(pipe, tex_xfer);

   /* destroy the temp / dest surface */
   util_destroy_rgba_surface(dst_texture, dst_surface);

   pipe_sampler_view_release(pipe, &src_view);
}
예제 #7
0
static void GLAPIENTRY
_mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax");
      return;
   }

   if (target != GL_MINMAX) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmax(target)");
      return;
   }

   if (format != GL_RED &&
       format != GL_GREEN &&
       format != GL_BLUE &&
       format != GL_ALPHA &&
       format != GL_RGB &&
       format != GL_BGR &&
       format != GL_RGBA &&
       format != GL_BGRA &&
       format != GL_ABGR_EXT &&
       format != GL_LUMINANCE &&
       format != GL_LUMINANCE_ALPHA) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMax(format)");
   }

   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax(format or type)");
      return;
   }


   values = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack, 2, 1, 1,
                                        format, type, values, "glGetMinmax");
   if (!values)
      return;

   {
      GLfloat minmax[2][4];
      minmax[0][RCOMP] = CLAMP(ctx->MinMax.Min[RCOMP], 0.0F, 1.0F);
      minmax[0][GCOMP] = CLAMP(ctx->MinMax.Min[GCOMP], 0.0F, 1.0F);
      minmax[0][BCOMP] = CLAMP(ctx->MinMax.Min[BCOMP], 0.0F, 1.0F);
      minmax[0][ACOMP] = CLAMP(ctx->MinMax.Min[ACOMP], 0.0F, 1.0F);
      minmax[1][RCOMP] = CLAMP(ctx->MinMax.Max[RCOMP], 0.0F, 1.0F);
      minmax[1][GCOMP] = CLAMP(ctx->MinMax.Max[GCOMP], 0.0F, 1.0F);
      minmax[1][BCOMP] = CLAMP(ctx->MinMax.Max[BCOMP], 0.0F, 1.0F);
      minmax[1][ACOMP] = CLAMP(ctx->MinMax.Max[ACOMP], 0.0F, 1.0F);
      _mesa_pack_rgba_span_float(ctx, 2, minmax,
                                 format, type, values, &ctx->Pack, 0x0);
   }

   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);

   if (reset) {
      _mesa_ResetMinmax(GL_MINMAX);
   }
}
예제 #8
0
파일: colortab.c 프로젝트: Starlink/mesa
void GLAPIENTRY
_mesa_GetColorTable( GLenum target, GLenum format,
                     GLenum type, GLvoid *data )
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
   struct gl_color_table *table = NULL;
   GLfloat rgba[MAX_COLOR_TABLE_SIZE][4];
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

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

   switch (target) {
      case GL_TEXTURE_1D:
         table = &texUnit->Current1D->Palette;
         break;
      case GL_TEXTURE_2D:
         table = &texUnit->Current2D->Palette;
         break;
      case GL_TEXTURE_3D:
         table = &texUnit->Current3D->Palette;
         break;
      case GL_TEXTURE_CUBE_MAP_ARB:
         if (!ctx->Extensions.ARB_texture_cube_map) {
            _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
            return;
         }
         table = &texUnit->CurrentCubeMap->Palette;
         break;
      case GL_SHARED_TEXTURE_PALETTE_EXT:
         table = &ctx->Texture.Palette;
         break;
      case GL_COLOR_TABLE:
         table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
         break;
      case GL_TEXTURE_COLOR_TABLE_SGI:
         if (!ctx->Extensions.SGI_texture_color_table) {
            _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
            return;
         }
         table = &(texUnit->ColorTable);
         break;
      case GL_POST_CONVOLUTION_COLOR_TABLE:
         table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
         break;
      case GL_POST_COLOR_MATRIX_COLOR_TABLE:
         table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
         break;
      default:
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
         return;
   }

   ASSERT(table);

   if (table->Size <= 0) {
      return;
   }

   switch (table->_BaseFormat) {
   case GL_ALPHA:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] = 0;
            rgba[i][GCOMP] = 0;
            rgba[i][BCOMP] = 0;
            rgba[i][ACOMP] = table->TableF[i];
         }
      }
      break;
   case GL_LUMINANCE:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] = table->TableF[i];
            rgba[i][ACOMP] = 1.0F;
         }
      }
      break;
   case GL_LUMINANCE_ALPHA:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] = table->TableF[i*2+0];
            rgba[i][ACOMP] = table->TableF[i*2+1];
         }
      }
      break;
   case GL_INTENSITY:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] =
            rgba[i][GCOMP] =
            rgba[i][BCOMP] =
            rgba[i][ACOMP] = table->TableF[i];
         }
      }
      break;
   case GL_RGB:
      {
         GLuint i;
         for (i = 0; i < table->Size; i++) {
            rgba[i][RCOMP] = table->TableF[i*3+0];
            rgba[i][GCOMP] = table->TableF[i*3+1];
            rgba[i][BCOMP] = table->TableF[i*3+2];
            rgba[i][ACOMP] = 1.0F;
         }
      }
      break;
   case GL_RGBA:
      _mesa_memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat));
      break;
   default:
      _mesa_problem(ctx, "bad table format in glGetColorTable");
      return;
   }

   if (ctx->Pack.BufferObj->Name) {
      /* pack color table into PBO */
      GLubyte *buf;
      if (!_mesa_validate_pbo_access(1, &ctx->Pack, table->Size, 1, 1,
                                     format, type, data)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetColorTable(invalid PBO access)");
         return;
      }
      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                                              GL_WRITE_ONLY_ARB,
                                              ctx->Pack.BufferObj);
      if (!buf) {
         /* buffer is already mapped - that's an error */
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetColorTable(PBO is mapped)");
         return;
      }
      data = ADD_POINTERS(buf, data);
   }

   _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
                              format, type, data, &ctx->Pack, 0x0);

   if (ctx->Pack.BufferObj->Name) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                              ctx->Pack.BufferObj);
   }
}
/**
 * Get an uncompressed color texture image.
 */
static void
get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
                          GLenum format, GLenum type, GLvoid *pixels,
                          struct gl_texture_image *texImage,
                          GLbitfield transferOps)
{
   /* don't want to apply sRGB -> RGB conversion here so override the format */
   const gl_format texFormat =
      _mesa_get_srgb_format_linear(texImage->TexFormat);
   const GLuint width = texImage->Width;
   const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format);
   GLenum rebaseFormat = GL_NONE;
   GLuint height = texImage->Height;
   GLuint depth = texImage->Depth;
   GLuint img, row;
   GLfloat (*rgba)[4];
   GLuint (*rgba_uint)[4];
   GLboolean tex_is_integer = _mesa_is_format_integer_color(texImage->TexFormat);
   GLboolean tex_is_uint = _mesa_is_format_unsigned(texImage->TexFormat);

   /* Allocate buffer for one row of texels */
   rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
   rgba_uint = (GLuint (*)[4]) rgba;
   if (!rgba) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
      return;
   }

   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      depth = height;
      height = 1;
   }

   if (texImage->_BaseFormat == GL_LUMINANCE ||
       texImage->_BaseFormat == GL_INTENSITY ||
       texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
      /* If a luminance (or intensity) texture is read back as RGB(A), the
       * returned value should be (L,0,0,1), not (L,L,L,1).  Set rebaseFormat
       * here to get G=B=0.
       */
      rebaseFormat = texImage->_BaseFormat;
   }
   else if ((texImage->_BaseFormat == GL_RGBA ||
             texImage->_BaseFormat == GL_RGB ||
             texImage->_BaseFormat == GL_RG) &&
            (destBaseFormat == GL_LUMINANCE ||
             destBaseFormat == GL_LUMINANCE_ALPHA ||
             destBaseFormat == GL_LUMINANCE_INTEGER_EXT ||
             destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) {
      /* If we're reading back an RGB(A) texture as luminance then we need
       * to return L=tex(R).  Note, that's different from glReadPixels which
       * returns L=R+G+B.
       */
      rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */
   }

   for (img = 0; img < depth; img++) {
      GLubyte *srcMap;
      GLint rowstride;

      /* map src texture buffer */
      ctx->Driver.MapTextureImage(ctx, texImage, img,
                                  0, 0, width, height, GL_MAP_READ_BIT,
                                  &srcMap, &rowstride);
      if (srcMap) {
         for (row = 0; row < height; row++) {
            const GLubyte *src = srcMap + row * rowstride;
            void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                             width, height, format, type,
                                             img, row, 0);

	    if (tex_is_integer) {
	       _mesa_unpack_uint_rgba_row(texFormat, width, src, rgba_uint);
               if (rebaseFormat)
                  _mesa_rebase_rgba_uint(width, rgba_uint, rebaseFormat);
               if (tex_is_uint) {
                  _mesa_pack_rgba_span_from_uints(ctx, width,
                                                  (GLuint (*)[4]) rgba_uint,
                                                  format, type, dest);
               } else {
                  _mesa_pack_rgba_span_from_ints(ctx, width,
                                                 (GLint (*)[4]) rgba_uint,
                                                 format, type, dest);
               }
	    } else {
	       _mesa_unpack_rgba_row(texFormat, width, src, rgba);
               if (rebaseFormat)
                  _mesa_rebase_rgba_float(width, rgba, rebaseFormat);
	       _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
					  format, type, dest,
					  &ctx->Pack, transferOps);
	    }
	 }

         /* Unmap the src texture buffer */
         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         break;
      }
   }

   free(rgba);
}
/**
 * Get a color texture image with decompression.
 */
static void
get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions,
                        GLenum format, GLenum type, GLvoid *pixels,
                        struct gl_texture_image *texImage,
                        GLbitfield transferOps)
{
   /* don't want to apply sRGB -> RGB conversion here so override the format */
   const gl_format texFormat =
      _mesa_get_srgb_format_linear(texImage->TexFormat);
   const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
   const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format);
   GLenum rebaseFormat = GL_NONE;
   const GLuint width = texImage->Width;
   const GLuint height = texImage->Height;
   const GLuint depth = texImage->Depth;
   GLfloat *tempImage, *srcRow;
   GLuint row;

   /* Decompress into temp float buffer, then pack into user buffer */
   tempImage = (GLfloat *) malloc(width * height * depth
                                  * 4 * sizeof(GLfloat));
   if (!tempImage) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
      return;
   }

   /* Decompress the texture image - results in 'tempImage' */
   {
      GLubyte *srcMap;
      GLint srcRowStride;

      ctx->Driver.MapTextureImage(ctx, texImage, 0,
                                  0, 0, width, height,
                                  GL_MAP_READ_BIT,
                                  &srcMap, &srcRowStride);
      if (srcMap) {
         _mesa_decompress_image(texFormat, width, height,
                                srcMap, srcRowStride, tempImage);

         ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
      }
      else {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
         free(tempImage);
         return;
      }
   }

   if (baseFormat == GL_LUMINANCE ||
       baseFormat == GL_INTENSITY ||
       baseFormat == GL_LUMINANCE_ALPHA) {
      /* If a luminance (or intensity) texture is read back as RGB(A), the
       * returned value should be (L,0,0,1), not (L,L,L,1).  Set rebaseFormat
       * here to get G=B=0.
       */
      rebaseFormat = texImage->_BaseFormat;
   }
   else if ((baseFormat == GL_RGBA ||
             baseFormat == GL_RGB  ||
             baseFormat == GL_RG) &&
            (destBaseFormat == GL_LUMINANCE ||
             destBaseFormat == GL_LUMINANCE_ALPHA ||
             destBaseFormat == GL_LUMINANCE_INTEGER_EXT ||
             destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) {
      /* If we're reading back an RGB(A) texture as luminance then we need
       * to return L=tex(R).  Note, that's different from glReadPixels which
       * returns L=R+G+B.
       */
      rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */
   }

   if (rebaseFormat) {
      _mesa_rebase_rgba_float(width * height, (GLfloat (*)[4]) tempImage,
                              rebaseFormat);
   }

   srcRow = tempImage;
   for (row = 0; row < height; row++) {
      void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                       width, height, format, type,
                                       0, row, 0);

      _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow,
                                 format, type, dest, &ctx->Pack, transferOps);
      srcRow += width * 4;
   }

   free(tempImage);
}
예제 #11
0
/**
 * glGetTexImagefor RGBA, Luminance, etc. pixels.
 * This is the slow way since we use texture sampling.
 */
static void
get_tex_rgba(GLcontext *ctx, GLuint dimensions,
             GLenum format, GLenum type, GLvoid *pixels,
             const struct gl_texture_image *texImage)
{
   const GLint width = texImage->Width;
   const GLint height = texImage->Height;
   const GLint depth = texImage->Depth;
   /* Normally, no pixel transfer ops are performed during glGetTexImage.
    * The only possible exception is component clamping to [0,1].
    */
   GLbitfield transferOps = 0x0;
   GLint img, row;

   for (img = 0; img < depth; img++) {
      for (row = 0; row < height; row++) {
         void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
                                          width, height, format, type,
                                          img, row, 0);
         GLfloat rgba[MAX_WIDTH][4];
         GLint col;
         GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);

         /* clamp does not apply to GetTexImage (final conversion)?
          * Looks like we need clamp though when going from format
          * containing negative values to unsigned format.
          */
         if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
            transferOps |= IMAGE_CLAMP_BIT;
         }
         else if (!type_with_negative_values(type) &&
                  (dataType == GL_FLOAT ||
                   dataType == GL_SIGNED_NORMALIZED)) {
            transferOps |= IMAGE_CLAMP_BIT;
         }

         for (col = 0; col < width; col++) {
            texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
            if (texImage->_BaseFormat == GL_ALPHA) {
               rgba[col][RCOMP] = 0.0F;
               rgba[col][GCOMP] = 0.0F;
               rgba[col][BCOMP] = 0.0F;
            }
            else if (texImage->_BaseFormat == GL_LUMINANCE) {
               rgba[col][GCOMP] = 0.0F;
               rgba[col][BCOMP] = 0.0F;
               rgba[col][ACOMP] = 1.0F;
            }
            else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
               rgba[col][GCOMP] = 0.0F;
               rgba[col][BCOMP] = 0.0F;
            }
            else if (texImage->_BaseFormat == GL_INTENSITY) {
               rgba[col][GCOMP] = 0.0F;
               rgba[col][BCOMP] = 0.0F;
               rgba[col][ACOMP] = 1.0F;
            }
         }
         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                    format, type, dest,
                                    &ctx->Pack, transferOps);
      }
   }
}
예제 #12
0
/**
 * This is the software fallback for Driver.GetTexImage().
 * All error checking will have been done before this routine is called.
 */
void
_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
                   GLenum format, GLenum type, GLvoid *pixels,
                   struct gl_texture_object *texObj,
                   struct gl_texture_image *texImage)
{
   const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;

   if (ctx->Pack.BufferObj->Name) {
      /* Packing texture image into a PBO.
       * Map the (potentially) VRAM-based buffer into our process space so
       * we can write into it with the code below.
       * A hardware driver might use a sophisticated blit to move the
       * texture data to the PBO if the PBO is in VRAM along with the texture.
       */
      GLubyte *buf = (GLubyte *)
         ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                               GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
      if (!buf) {
         /* buffer is already mapped - that's an error */
         _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
         return;
      }
      /* <pixels> was an offset into the PBO.
       * Now make it a real, client-side pointer inside the mapped region.
       */
      pixels = ADD_POINTERS(buf, pixels);
   }
   else if (!pixels) {
      /* not an error */
      return;
   }

   {
      const GLint width = texImage->Width;
      const GLint height = texImage->Height;
      const GLint depth = texImage->Depth;
      GLint img, row;
      for (img = 0; img < depth; img++) {
         for (row = 0; row < height; row++) {
            /* compute destination address in client memory */
            GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
                                                width, height, format, type,
                                                img, row, 0);
            assert(dest);

            if (format == GL_COLOR_INDEX) {
               GLuint indexRow[MAX_WIDTH];
               GLint col;
               /* Can't use FetchTexel here because that returns RGBA */
               if (texImage->TexFormat->IndexBits == 8) {
                  const GLubyte *src = (const GLubyte *) texImage->Data;
                  src += width * (img * texImage->Height + row);
                  for (col = 0; col < width; col++) {
                     indexRow[col] = src[col];
                  }
               }
               else if (texImage->TexFormat->IndexBits == 16) {
                  const GLushort *src = (const GLushort *) texImage->Data;
                  src += width * (img * texImage->Height + row);
                  for (col = 0; col < width; col++) {
                     indexRow[col] = src[col];
                  }
               }
               else {
                  _mesa_problem(ctx,
                                "Color index problem in _mesa_GetTexImage");
               }
               _mesa_pack_index_span(ctx, width, type, dest,
                                     indexRow, &ctx->Pack,
                                     0 /* no image transfer */);
            }
            else if (format == GL_DEPTH_COMPONENT) {
               GLfloat depthRow[MAX_WIDTH];
               GLint col;
               for (col = 0; col < width; col++) {
                  (*texImage->FetchTexelf)(texImage, col, row, img,
                                           depthRow + col);
               }
               _mesa_pack_depth_span(ctx, width, dest, type,
                                     depthRow, &ctx->Pack);
            }
            else if (format == GL_DEPTH_STENCIL_EXT) {
               /* XXX Note: we're bypassing texImage->FetchTexel()! */
               const GLuint *src = (const GLuint *) texImage->Data;
               src += width * row + width * height * img;
               _mesa_memcpy(dest, src, width * sizeof(GLuint));
               if (ctx->Pack.SwapBytes) {
                  _mesa_swap4((GLuint *) dest, width);
               }
            }
            else if (format == GL_YCBCR_MESA) {
               /* No pixel transfer */
               const GLint rowstride = texImage->RowStride;
               MEMCPY(dest,
                      (const GLushort *) texImage->Data + row * rowstride,
                      width * sizeof(GLushort));
               /* check for byte swapping */
               if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
                    && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
                   (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
                    && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
                  if (!ctx->Pack.SwapBytes)
                     _mesa_swap2((GLushort *) dest, width);
               }
               else if (ctx->Pack.SwapBytes) {
                  _mesa_swap2((GLushort *) dest, width);
               }
            }
#if FEATURE_EXT_texture_sRGB
            else if (is_srgb_teximage(texImage)) {
               /* special case this since need to backconvert values */
               /* convert row to RGBA format */
               GLfloat rgba[MAX_WIDTH][4];
               GLint col;
               GLbitfield transferOps = 0x0;

               for (col = 0; col < width; col++) {
                  (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
                  if (texImage->_BaseFormat == GL_LUMINANCE) {
                     rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                  }
                  else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
                     rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                  }
                  else if (texImage->_BaseFormat == GL_RGB ||
                     texImage->_BaseFormat == GL_RGBA) {
                     rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
                     rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
                     rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
                  }
               }
               _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                          format, type, dest,
                                          &ctx->Pack, transferOps);
            }
#endif /* FEATURE_EXT_texture_sRGB */
            else {
               /* general case:  convert row to RGBA format */
               GLfloat rgba[MAX_WIDTH][4];
               GLint col;
               GLbitfield transferOps = 0x0;

               /* clamp does not apply to GetTexImage (final conversion)?
                * Looks like we need clamp though when going from format
                * containing negative values to unsigned format.
                */
               if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA)
                  transferOps |= IMAGE_CLAMP_BIT;
               else if (!type_with_negative_values(type) &&
                        (texImage->TexFormat->DataType == GL_FLOAT ||
                         texImage->TexFormat->DataType == GL_SIGNED_NORMALIZED))
                  transferOps |= IMAGE_CLAMP_BIT;

               for (col = 0; col < width; col++) {
                  (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
                  if (texImage->_BaseFormat == GL_ALPHA) {
                     rgba[col][RCOMP] = 0.0;
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                  }
                  else if (texImage->_BaseFormat == GL_LUMINANCE) {
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                     rgba[col][ACOMP] = 1.0;
                  }
                  else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                  }
                  else if (texImage->_BaseFormat == GL_INTENSITY) {
                     rgba[col][GCOMP] = 0.0;
                     rgba[col][BCOMP] = 0.0;
                     rgba[col][ACOMP] = 1.0;
                  }
               }
               _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                          format, type, dest,
                                          &ctx->Pack, transferOps);
            } /* format */
         } /* row */
      } /* img */
   }

   if (ctx->Pack.BufferObj->Name) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                              ctx->Pack.BufferObj);
   }
}