示例#1
0
void GLAPIENTRY
_mesa_GetPixelMapfv( GLenum map, GLfloat *values )
{
   GET_CURRENT_CONTEXT(ctx);
   GLuint mapsize, i;
   const struct gl_pixelmap *pm;

   ASSERT_OUTSIDE_BEGIN_END(ctx);

   pm = get_pixelmap(ctx, map);
   if (!pm) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
      return;
   }

   mapsize = pm->Size;

   if (ctx->Pack.BufferObj->Name) {
      /* pack pixelmap into PBO */
      GLubyte *buf;
      /* Note, need to use DefaultPacking and Pack's buffer object */
      ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
                                     GL_INTENSITY, GL_FLOAT, values)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetPixelMapfv(invalid PBO access)");
         return;
      }
      /* restore */
      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
      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,
                     "glGetPixelMapfv(PBO is mapped)");
         return;
      }
      values = (GLfloat *) ADD_POINTERS(buf, values);
   }
   else if (!values) {
      return;
   }

   if (map == GL_PIXEL_MAP_S_TO_S) {
      /* special case */
      for (i = 0; i < mapsize; i++) {
         values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
      }
   }
   else {
      MEMCPY(values, pm->Map, mapsize * sizeof(GLfloat));
   }

   if (ctx->Pack.BufferObj->Name) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                              ctx->Pack.BufferObj);
   }
}
示例#2
0
/**
 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
 */
static GLboolean
validate_pbo_access(struct gl_context *ctx,
                    struct gl_pixelstore_attrib *pack, GLsizei mapsize,
                    GLenum format, GLenum type, GLsizei clientMemSize,
                    const GLvoid *ptr)
{
    GLboolean ok;

    /* Note, need to use DefaultPacking and Unpack's buffer object */
    _mesa_reference_buffer_object(ctx,
                                  &ctx->DefaultPacking.BufferObj,
                                  pack->BufferObj);

    ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
                                   format, type, clientMemSize, ptr);

    /* restore */
    _mesa_reference_buffer_object(ctx,
                                  &ctx->DefaultPacking.BufferObj,
                                  ctx->Shared->NullBufferObj);

    if (!ok) {
        if (_mesa_is_bufferobj(pack->BufferObj)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "gl[Get]PixelMap*v(out of bounds PBO access)");
        } else {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glGetnPixelMap*vARB(out of bounds access:"
                        " bufSize (%d) is too small)", clientMemSize);
        }
    }
    return ok;
}
示例#3
0
/**
 * Check if an unpack PBO is active prior to fetching a texture image.
 * If so, do bounds checking and map the buffer into main memory.
 * Any errors detected will be recorded.
 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
 */
const GLvoid *
_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions,
			    GLsizei width, GLsizei height, GLsizei depth,
			    GLenum format, GLenum type, const GLvoid *pixels,
			    const struct gl_pixelstore_attrib *unpack,
			    const char *funcName)
{
   GLubyte *buf;

   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
      /* no PBO */
      return pixels;
   }
   if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
                                  format, type, INT_MAX, pixels)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)",
                  funcName, dimensions);
      return NULL;
   }

   buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
                                                unpack->BufferObj->Size,
						GL_MAP_READ_BIT,
						unpack->BufferObj,
                                                MAP_INTERNAL);
   if (!buf) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName,
                  dimensions);
      return NULL;
   }

   return ADD_POINTERS(buf, pixels);
}
示例#4
0
/* Unlike the other intel_pixel_* functions, the expectation here is
 * that the incoming data is not in a PBO.  With the XY_TEXT blit
 * method, there's no benefit haveing it in a PBO, but we could
 * implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit
 * PBO bitmaps.  I think they are probably pretty rare though - I
 * wonder if Xgl uses them?
 */
static const GLubyte *map_pbo( struct gl_context *ctx,
			       GLsizei width, GLsizei height,
			       const struct gl_pixelstore_attrib *unpack,
			       const GLubyte *bitmap )
{
   GLubyte *buf;

   if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
				  GL_COLOR_INDEX, GL_BITMAP,
				  INT_MAX, (const GLvoid *) bitmap)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
      return NULL;
   }

   buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size,
						GL_MAP_READ_BIT,
						unpack->BufferObj,
                                                MAP_INTERNAL);
   if (!buf) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
      return NULL;
   }

   return ADD_POINTERS(buf, bitmap);
}
示例#5
0
/**
 * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
 */
static GLboolean
validate_pbo_access(GLcontext *ctx, struct gl_pixelstore_attrib *pack,
                    GLsizei mapsize, GLenum format, GLenum type,
                    const GLvoid *ptr)
{
   GLboolean ok;

   /* Note, need to use DefaultPacking and Unpack's buffer object */
   _mesa_reference_buffer_object(ctx,
                                 &ctx->DefaultPacking.BufferObj,
                                 pack->BufferObj);

   ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
                                  format, type, ptr);

   /* restore */
   _mesa_reference_buffer_object(ctx,
                                 &ctx->DefaultPacking.BufferObj,
                                 ctx->Shared->NullBufferObj);

   if (!ok) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glPixelMap(invalid PBO access)");
   }
   return ok;
}
示例#6
0
void GLAPIENTRY
_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
      return;
   }

   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
      /* test that mapsize is a power of two */
      if (_mesa_bitcount((GLuint) mapsize) != 1) {
	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
         return;
      }
   }

   FLUSH_VERTICES(ctx, _NEW_PIXEL);

   if (ctx->Unpack.BufferObj->Name) {
      /* unpack pixelmap from PBO */
      GLubyte *buf;
      /* Note, need to use DefaultPacking and Unpack's buffer object */
      ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
                                     GL_INTENSITY, GL_FLOAT, values)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glPixelMapfv(invalid PBO access)");
         return;
      }
      /* restore */
      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
                                              GL_READ_ONLY_ARB,
                                              ctx->Unpack.BufferObj);
      if (!buf) {
         /* buffer is already mapped - that's an error */
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glPixelMapfv(PBO is mapped)");
         return;
      }
      values = (const GLfloat *) ADD_POINTERS(buf, values);
   }
   else if (!values) {
      return;
   }

   store_pixelmap(ctx, map, mapsize, values);

   if (ctx->Unpack.BufferObj->Name) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
                              ctx->Unpack.BufferObj);
   }
}
示例#7
0
void GLAPIENTRY
_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
		  GLenum format, GLenum type, GLvoid *pixels )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   FLUSH_CURRENT(ctx, 0);

   if (width < 0 || height < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE,
                   "glReadPixels(width=%d height=%d)", width, height );
      return;
   }

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

   if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
      /* found an error */
      return;
   }

   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "glReadPixels(incomplete framebuffer)" );
      return;
   }

   if (!_mesa_source_buffer_exists(ctx, format)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
      return;
   }

   if (ctx->Pack.BufferObj->Name) {
      if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
                                     format, type, pixels)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glReadPixels(invalid PBO access)");
         return;
      }

      if (ctx->Pack.BufferObj->Pointer) {
         /* buffer is mapped - that's an error */
         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
         return;
      }
   }

   ctx->Driver.ReadPixels(ctx, x, y, width, height,
			  format, type, &ctx->Pack, pixels);
}
示例#8
0
/**
 * Perform PBO validation for read operations with uncompressed textures.
 * If any GL errors are detected, false is returned, otherwise returns true.
 * \sa _mesa_validate_pbo_access
 */
bool
_mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions,
                          const struct gl_pixelstore_attrib *unpack,
                          GLsizei width, GLsizei height, GLsizei depth,
                          GLenum format, GLenum type,
                          GLsizei clientMemSize,
                          const GLvoid *ptr, const char *where)
{
   assert(dimensions == 1 || dimensions == 2 || dimensions == 3);

   if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
                                  format, type, clientMemSize, ptr)) {
      if (_mesa_is_bufferobj(unpack->BufferObj)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "%s(out of bounds PBO access)",
                     where);
      } else {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "%s(out of bounds access: bufSize (%d) is too small)",
                     where, clientMemSize);
      }
      return false;
   }

   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
      /* non-PBO access: no further validation to be done */
      return true;
   }

   if (_mesa_check_disallowed_mapping(unpack->BufferObj)) {
      /* buffer is already mapped - that's an error */
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)",
                  where);
      return false;
   }

   return true;
}
示例#9
0
/* Unlike the other intel_pixel_* functions, the expectation here is
 * that the incoming data is not in a PBO.  With the XY_TEXT blit
 * method, there's no benefit haveing it in a PBO, but we could
 * implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit
 * PBO bitmaps.  I think they are probably pretty rare though - I
 * wonder if Xgl uses them?
 */
static const GLubyte *map_pbo( GLcontext *ctx,
			       GLsizei width, GLsizei height,
			       const struct gl_pixelstore_attrib *unpack,
			       const GLubyte *bitmap )
{
   GLubyte *buf;

   if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
				  GL_COLOR_INDEX, GL_BITMAP,
				  (GLvoid *) bitmap)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
      return NULL;
   }

   buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
					   GL_READ_ONLY_ARB,
					   unpack->BufferObj);
   if (!buf) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
      return NULL;
   }

   return ADD_POINTERS(buf, bitmap);
}
示例#10
0
/*
 * Execute glDrawPixels
 */
static void GLAPIENTRY
_mesa_DrawPixels( GLsizei width, GLsizei height,
                  GLenum format, GLenum type, const GLvoid *pixels )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   if (width < 0 || height < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
      return;
   }

   /* We're not using the current vertex program, and the driver may install
    * it's own.
    */
   _mesa_set_vp_override(ctx, GL_TRUE);

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

   if (!valid_fragment_program(ctx)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glDrawPixels (invalid fragment program)");
      goto end;
   }

   if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) {
      /* the error was already recorded */
      goto end;
   }

   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "glDrawPixels(incomplete framebuffer)" );
      goto end;
   }

   if (!ctx->Current.RasterPosValid) {
      goto end; /* no-op, not an error */
   }

   if (ctx->RenderMode == GL_RENDER) {
      if (width > 0 && height > 0) {
         /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
         GLint x = IROUND(ctx->Current.RasterPos[0]);
         GLint y = IROUND(ctx->Current.RasterPos[1]);

         if (ctx->Unpack.BufferObj->Name) {
            /* unpack from PBO */
            if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
                                           format, type, pixels)) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glDrawPixels(invalid PBO access)");
               goto end;
            }
            if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
               /* buffer is mapped - that's an error */
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glDrawPixels(PBO is mapped)");
               goto end;
            }
         }

         ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
                                &ctx->Unpack, pixels);
      }
   }
   else if (ctx->RenderMode == GL_FEEDBACK) {
      /* Feedback the current raster pos info */
      FLUSH_CURRENT( ctx, 0 );
      _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
      _mesa_feedback_vertex( ctx,
                             ctx->Current.RasterPos,
                             ctx->Current.RasterColor,
                             ctx->Current.RasterIndex,
                             ctx->Current.RasterTexCoords[0] );
   }
   else {
      ASSERT(ctx->RenderMode == GL_SELECT);
      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
   }

end:
   _mesa_set_vp_override(ctx, GL_FALSE);
}
示例#11
0
static void GLAPIENTRY
_mesa_Bitmap( GLsizei width, GLsizei height,
              GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
              const GLubyte *bitmap )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   if (width < 0 || height < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
      return;
   }

   if (!ctx->Current.RasterPosValid) {
      return;    /* do nothing */
   }

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

   if (!valid_fragment_program(ctx)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glBitmap (invalid fragment program)");
      return;
   }

   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "glBitmap(incomplete framebuffer)");
      return;
   }

   if (ctx->RenderMode == GL_RENDER) {
      /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
      if (width > 0 && height > 0) {
         const GLfloat epsilon = 0.0001F;
         GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
         GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);

         if (ctx->Unpack.BufferObj->Name) {
            /* unpack from PBO */
            if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
                                           GL_COLOR_INDEX, GL_BITMAP,
                                           (GLvoid *) bitmap)) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glBitmap(invalid PBO access)");
               return;
            }
            if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
               /* buffer is mapped - that's an error */
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glBitmap(PBO is mapped)");
               return;
            }
         }

         ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
      }
   }
#if _HAVE_FULL_GL
   else if (ctx->RenderMode == GL_FEEDBACK) {
      FLUSH_CURRENT(ctx, 0);
      _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
      _mesa_feedback_vertex( ctx,
                             ctx->Current.RasterPos,
                             ctx->Current.RasterColor,
                             ctx->Current.RasterIndex, 
                             ctx->Current.RasterTexCoords[0] );
   }
   else {
      ASSERT(ctx->RenderMode == GL_SELECT);
      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
   }
#endif

   /* update raster position */
   ctx->Current.RasterPos[0] += xmove;
   ctx->Current.RasterPos[1] += ymove;
}
示例#12
0
void GLAPIENTRY
_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
		      GLenum format, GLenum type, GLsizei bufSize,
                      GLvoid *pixels )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   FLUSH_CURRENT(ctx, 0);

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
                  width, height,
                  _mesa_lookup_enum_by_nr(format),
                  _mesa_lookup_enum_by_nr(type),
                  pixels);

   if (width < 0 || height < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE,
                   "glReadPixels(width=%d height=%d)", width, height );
      return;
   }

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

   if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
      /* found an error */
      return;
   }

   /* Check that the destination format and source buffer are both
    * integer-valued or both non-integer-valued.
    */
   if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
      const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
      const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
      const GLboolean dstInteger = _mesa_is_integer_format(format);
      if (dstInteger != srcInteger) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glReadPixels(integer / non-integer format mismatch");
         return;
      }
   }

   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "glReadPixels(incomplete framebuffer)" );
      return;
   }

   if (ctx->ReadBuffer->Name != 0 && ctx->ReadBuffer->Visual.samples > 0) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
      return;
   }

   if (!_mesa_source_buffer_exists(ctx, format)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
      return;
   }

   if (width == 0 || height == 0)
      return; /* nothing to do */

   if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
                                  format, type, bufSize, pixels)) {
      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glReadPixels(out of bounds PBO access)");
      } else {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glReadnPixelsARB(out of bounds access:"
                     " bufSize (%d) is too small)", bufSize);
      }
      return;
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
       _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
      /* buffer is mapped - that's an error */
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
      return;
   }

   ctx->Driver.ReadPixels(ctx, x, y, width, height,
			  format, type, &ctx->Pack, pixels);
}
示例#13
0
/*
 * Execute glDrawPixels
 */
void GLAPIENTRY
_mesa_DrawPixels( GLsizei width, GLsizei height,
                  GLenum format, GLenum type, const GLvoid *pixels )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   if (width < 0 || height < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
      return;
   }

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

   if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glDrawPixels (invalid fragment program)");
      return;
   }

   if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) {
      /* found an error */
      return;
   }

   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "glDrawPixels(incomplete framebuffer)" );
      return;
   }

   if (!ctx->Current.RasterPosValid) {
      return;
   }

   if (ctx->RenderMode == GL_RENDER) {
      /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
      GLint x = IROUND(ctx->Current.RasterPos[0]);
      GLint y = IROUND(ctx->Current.RasterPos[1]);

      if (ctx->Unpack.BufferObj->Name) {
         /* unpack from PBO */
         if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
                                        format, type, pixels)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glDrawPixels(invalid PBO access)");
            return;
         }
         if (ctx->Unpack.BufferObj->Pointer) {
            /* buffer is mapped - that's an error */
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glDrawPixels(PBO is mapped)");
            return;
         }
      }

      ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
			     &ctx->Unpack, pixels);
   }
   else if (ctx->RenderMode == GL_FEEDBACK) {
      /* Feedback the current raster pos info */
      FLUSH_CURRENT( ctx, 0 );
      FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
      _mesa_feedback_vertex( ctx,
                             ctx->Current.RasterPos,
                             ctx->Current.RasterColor,
                             ctx->Current.RasterIndex,
                             ctx->Current.RasterTexCoords[0] );
   }
   else {
      ASSERT(ctx->RenderMode == GL_SELECT);
      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
   }
}
/**
 * Do error checking for a glGetTexImage() call.
 * \return GL_TRUE if any error, GL_FALSE if no errors.
 */
static GLboolean
getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
                        GLenum format, GLenum type, GLsizei clientMemSize,
                        GLvoid *pixels )
{
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
   const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
   GLenum baseFormat, err;

   if (!legal_getteximage_target(ctx, target)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
      return GL_TRUE;
   }

   assert(maxLevels != 0);
   if (level < 0 || level >= maxLevels) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
      return GL_TRUE;
   }

   err = _mesa_error_check_format_and_type(ctx, format, type);
   if (err != GL_NO_ERROR) {
      _mesa_error(ctx, err, "glGetTexImage(format/type)");
      return GL_TRUE;
   }

   texObj = _mesa_get_current_tex_object(ctx, target);

   if (!texObj) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
      return GL_TRUE;
   }

   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
   if (!texImage) {
      /* non-existant texture image */
      return GL_TRUE;
   }

   baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
      
   /* Make sure the requested image format is compatible with the
    * texture's format.
    */
   if (_mesa_is_color_format(format)
       && !_mesa_is_color_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_depth_format(format)
            && !_mesa_is_depth_format(baseFormat)
            && !_mesa_is_depthstencil_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_ycbcr_format(format)
            && !_mesa_is_ycbcr_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_depthstencil_format(format)
            && !_mesa_is_depthstencil_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_dudv_format(format)
            && !_mesa_is_dudv_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }

   if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
                                  texImage->Height, texImage->Depth,
                                  format, type, clientMemSize, pixels)) {
      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetTexImage(out of bounds PBO access)");
      } else {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetnTexImageARB(out of bounds access:"
                     " bufSize (%d) is too small)", clientMemSize);
      }
      return GL_TRUE;
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      /* PBO should not be mapped */
      if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetTexImage(PBO is mapped)");
         return GL_TRUE;
      }
   }

   return GL_FALSE;
}
示例#15
0
/**
 * Do error checking for a glGetTexImage() call.
 * \return GL_TRUE if any error, GL_FALSE if no errors.
 */
static GLboolean
getteximage_error_check(GLcontext *ctx, GLenum target, GLint level,
                        GLenum format, GLenum type, GLvoid *pixels )
{
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   const GLuint maxLevels = _mesa_max_texture_levels(ctx, target);
   GLenum baseFormat;

   if (maxLevels == 0) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
      return GL_TRUE;
   }

   if (level < 0 || level >= maxLevels) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
      return GL_TRUE;
   }

   if (_mesa_sizeof_packed_type(type) <= 0) {
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
      return GL_TRUE;
   }

   if (_mesa_components_in_format(format) <= 0 ||
       format == GL_STENCIL_INDEX) {
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
      return GL_TRUE;
   }

   if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
      return GL_TRUE;
   }

   if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
      return GL_TRUE;
   }

   if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
      return GL_TRUE;
   }

   if (!ctx->Extensions.EXT_packed_depth_stencil
       && _mesa_is_depthstencil_format(format)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
      return GL_TRUE;
   }

   if (!ctx->Extensions.ATI_envmap_bumpmap
       && _mesa_is_dudv_format(format)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
      return GL_TRUE;
   }

   texObj = _mesa_get_current_tex_object(ctx, target);

   if (!texObj || _mesa_is_proxy_texture(target)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
      return GL_TRUE;
   }

   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
   if (!texImage) {
      /* out of memory */
      return GL_TRUE;
   }

   baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
      
   /* Make sure the requested image format is compatible with the
    * texture's format.  Note that a color index texture can be converted
    * to RGBA so that combo is allowed.
    */
   if (_mesa_is_color_format(format)
       && !_mesa_is_color_format(baseFormat)
       && !_mesa_is_index_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_index_format(format)
            && !_mesa_is_index_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_depth_format(format)
            && !_mesa_is_depth_format(baseFormat)
            && !_mesa_is_depthstencil_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_ycbcr_format(format)
            && !_mesa_is_ycbcr_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_depthstencil_format(format)
            && !_mesa_is_depthstencil_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }
   else if (_mesa_is_dudv_format(format)
            && !_mesa_is_dudv_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
      return GL_TRUE;
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      /* packing texture image into a PBO */
      const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
      if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
                                     texImage->Height, texImage->Depth,
                                     format, type, pixels)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetTexImage(out of bounds PBO write)");
         return GL_TRUE;
      }

      /* PBO should not be mapped */
      if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetTexImage(PBO is mapped)");
         return GL_TRUE;
      }
   }

   return GL_FALSE;
}
示例#16
0
/*
 * Execute glDrawPixels
 */
static void GLAPIENTRY
_mesa_DrawPixels( GLsizei width, GLsizei height,
                  GLenum format, GLenum type, const GLvoid *pixels )
{
   GLenum err;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n",
                  width, height,
                  _mesa_lookup_enum_by_nr(format),
                  _mesa_lookup_enum_by_nr(type),
                  pixels,
                  _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
                  IROUND(ctx->Current.RasterPos[0]),
                  IROUND(ctx->Current.RasterPos[1]));


   if (width < 0 || height < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0)" );
      return;
   }

   /* We're not using the current vertex program, and the driver may install
    * its own.  Note: this may dirty some state.
    */
   _mesa_set_vp_override(ctx, GL_TRUE);

   /* Note: this call does state validation */
   if (!_mesa_valid_to_render(ctx, "glDrawPixels")) {
      goto end;      /* the error code was recorded */
   }

   /* GL 3.0 introduced a new restriction on glDrawPixels() over what was in
    * GL_EXT_texture_integer.  From section 3.7.4 ("Rasterization of Pixel
    * Rectangles) on page 151 of the GL 3.0 specification:
    *
    *     "If format contains integer components, as shown in table 3.6, an
    *      INVALID OPERATION error is generated."
    *
    * Since DrawPixels rendering would be merely undefined if not an error (due
    * to a lack of defined mapping from integer data to gl_Color fragment shader
    * input), NVIDIA's implementation also just returns this error despite
    * exposing GL_EXT_texture_integer, just return an error regardless.
    */
   if (_mesa_is_enum_format_integer(format)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(integer format)");
      goto end;
   }

   err = _mesa_error_check_format_and_type(ctx, format, type);
   if (err != GL_NO_ERROR) {
      _mesa_error(ctx, err, "glDrawPixels(invalid format %s and/or type %s)",
                  _mesa_lookup_enum_by_nr(format),
                  _mesa_lookup_enum_by_nr(type));
      goto end;
   }

   /* do special format-related checks */
   switch (format) {
   case GL_STENCIL_INDEX:
   case GL_DEPTH_COMPONENT:
   case GL_DEPTH_STENCIL_EXT:
      /* these buffers must exist */
      if (!_mesa_dest_buffer_exists(ctx, format)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glDrawPixels(missing deest buffer)");
         goto end;
      }
      break;
   case GL_COLOR_INDEX:
      if (ctx->PixelMaps.ItoR.Size == 0 ||
          ctx->PixelMaps.ItoG.Size == 0 ||
          ctx->PixelMaps.ItoB.Size == 0) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                "glDrawPixels(drawing color index pixels into RGB buffer)");
         goto end;
      }
      break;
   default:
      /* for color formats it's not an error if the destination color
       * buffer doesn't exist.
       */
      break;
   }

   if (ctx->RasterDiscard) {
      goto end;
   }

   if (!ctx->Current.RasterPosValid) {
      goto end;  /* no-op, not an error */
   }

   if (ctx->RenderMode == GL_RENDER) {
      if (width > 0 && height > 0) {
         /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
         GLint x = IROUND(ctx->Current.RasterPos[0]);
         GLint y = IROUND(ctx->Current.RasterPos[1]);

         if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
            /* unpack from PBO */
            if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
                                           1, format, type, INT_MAX, pixels)) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glDrawPixels(invalid PBO access)");
               goto end;
            }
            if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
               /* buffer is mapped - that's an error */
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glDrawPixels(PBO is mapped)");
               goto end;
            }
         }

         ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
                                &ctx->Unpack, pixels);
      }
   }
   else if (ctx->RenderMode == GL_FEEDBACK) {
      /* Feedback the current raster pos info */
      FLUSH_CURRENT( ctx, 0 );
      _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
      _mesa_feedback_vertex( ctx,
                             ctx->Current.RasterPos,
                             ctx->Current.RasterColor,
                             ctx->Current.RasterTexCoords[0] );
   }
   else {
      ASSERT(ctx->RenderMode == GL_SELECT);
      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
   }

end:
   _mesa_set_vp_override(ctx, GL_FALSE);

   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
      _mesa_flush(ctx);
   }
}
示例#17
0
文件: colortab.c 项目: Starlink/mesa
/**
 * Update/replace all or part of a color table.  Helper function
 * used by _mesa_ColorTable() and _mesa_ColorSubTable().
 * The table->Table buffer should already be allocated.
 * \param start first entry to update
 * \param count number of entries to update
 * \param format format of user-provided table data
 * \param type datatype of user-provided table data
 * \param data user-provided table data
 * \param [rgba]Scale - RGBA scale factors
 * \param [rgba]Bias - RGBA bias factors
 */
static void
store_colortable_entries(GLcontext *ctx, struct gl_color_table *table,
			 GLsizei start, GLsizei count,
			 GLenum format, GLenum type, const GLvoid *data,
			 GLfloat rScale, GLfloat rBias,
			 GLfloat gScale, GLfloat gBias,
			 GLfloat bScale, GLfloat bBias,
			 GLfloat aScale, GLfloat aBias)
{
   if (ctx->Unpack.BufferObj->Name) {
      /* Get/unpack the color table data from a PBO */
      GLubyte *buf;
      if (!_mesa_validate_pbo_access(1, &ctx->Unpack, count, 1, 1,
                                     format, type, data)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glColor[Sub]Table(bad PBO access)");
         return;
      }
      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
                                              GL_READ_ONLY_ARB,
                                              ctx->Unpack.BufferObj);
      if (!buf) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glColor[Sub]Table(PBO mapped)");
         return;
      }
      data = ADD_POINTERS(buf, data);
   }


   {
      /* convert user-provided data to GLfloat values */
      GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4];
      GLfloat *tableF;
      GLint i;

      _mesa_unpack_color_span_float(ctx,
                                    count,         /* number of pixels */
                                    table->_BaseFormat, /* dest format */
                                    tempTab,       /* dest address */
                                    format, type,  /* src format/type */
                                    data,          /* src data */
                                    &ctx->Unpack,
                                    IMAGE_CLAMP_BIT); /* transfer ops */

      /* the destination */
      tableF = table->TableF;

      /* Apply scale & bias & clamp now */
      switch (table->_BaseFormat) {
         case GL_INTENSITY:
            for (i = 0; i < count; i++) {
               GLuint j = start + i;
               tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
            }
            break;
         case GL_LUMINANCE:
            for (i = 0; i < count; i++) {
               GLuint j = start + i;
               tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
            }
            break;
         case GL_ALPHA:
            for (i = 0; i < count; i++) {
               GLuint j = start + i;
               tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F);
            }
            break;
         case GL_LUMINANCE_ALPHA:
            for (i = 0; i < count; i++) {
               GLuint j = start + i;
               tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F);
               tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F);
            }
            break;
         case GL_RGB:
            for (i = 0; i < count; i++) {
               GLuint j = start + i;
               tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F);
               tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F);
               tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F);
            }
            break;
         case GL_RGBA:
            for (i = 0; i < count; i++) {
               GLuint j = start + i;
               tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F);
               tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F);
               tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F);
               tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F);
            }
            break;
         default:
            _mesa_problem(ctx, "Bad format in store_colortable_entries");
            return;
         }
   }

   /* update the ubyte table */
   {
      const GLint comps = _mesa_components_in_format(table->_BaseFormat);
      const GLfloat *tableF = table->TableF + start * comps;
      GLubyte *tableUB = table->TableUB + start * comps;
      GLint i;
      for (i = 0; i < count * comps; i++) {
         CLAMPED_FLOAT_TO_UBYTE(tableUB[i], tableF[i]);
      }
   }

   if (ctx->Unpack.BufferObj->Name) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
                              ctx->Unpack.BufferObj);
   }
}
示例#18
0
文件: pixel.c 项目: toastpp/toastpp
void GLAPIENTRY
_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
{
   GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" );
      return;
   }

   if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) {
      /* test that mapsize is a power of two */
      if (!_mesa_is_pow_two(mapsize)) {
	 _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
         return;
      }
   }

   FLUSH_VERTICES(ctx, _NEW_PIXEL);

   if (ctx->Unpack.BufferObj->Name) {
      /* unpack pixelmap from PBO */
      GLubyte *buf;
      /* Note, need to use DefaultPacking and Unpack's buffer object */
      ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj;
      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
                                     GL_INTENSITY, GL_UNSIGNED_SHORT,
                                     values)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glPixelMapusv(invalid PBO access)");
         return;
      }
      /* restore */
      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
                                              GL_READ_ONLY_ARB,
                                              ctx->Unpack.BufferObj);
      if (!buf) {
         /* buffer is already mapped - that's an error */
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glPixelMapusv(PBO is mapped)");
         return;
      }
      values = (const GLushort *) ADD_POINTERS(buf, values);
   }
   else if (!values) {
      return;
   }

   /* convert to floats */
   if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
      GLint i;
      for (i = 0; i < mapsize; i++) {
         fvalues[i] = (GLfloat) values[i];
      }
   }
   else {
      GLint i;
      for (i = 0; i < mapsize; i++) {
         fvalues[i] = USHORT_TO_FLOAT( values[i] );
      }
   }

   if (ctx->Unpack.BufferObj->Name) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
                              ctx->Unpack.BufferObj);
   }

   store_pixelmap(ctx, map, mapsize, fvalues);
}
示例#19
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);
   }
}
示例#20
0
static void GLAPIENTRY
_mesa_Bitmap( GLsizei width, GLsizei height,
              GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
              const GLubyte *bitmap )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   if (width < 0 || height < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
      return;
   }

   if (!ctx->Current.RasterPosValid) {
      return;    /* do nothing */
   }

   /* Note: this call does state validation */
   if (!_mesa_valid_to_render(ctx, "glBitmap")) {
      /* the error code was recorded */
      return;
   }

   if (ctx->RasterDiscard)
      return;

   if (ctx->RenderMode == GL_RENDER) {
      /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
      if (width > 0 && height > 0) {
         const GLfloat epsilon = 0.0001F;
         GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
         GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);

         if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
            /* unpack from PBO */
            if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
                                           1, GL_COLOR_INDEX, GL_BITMAP,
                                           INT_MAX, (const GLvoid *) bitmap)) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glBitmap(invalid PBO access)");
               return;
            }
            if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
               /* buffer is mapped - that's an error */
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glBitmap(PBO is mapped)");
               return;
            }
         }

         ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
      }
   }
#if _HAVE_FULL_GL
   else if (ctx->RenderMode == GL_FEEDBACK) {
      FLUSH_CURRENT(ctx, 0);
      _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
      _mesa_feedback_vertex( ctx,
                             ctx->Current.RasterPos,
                             ctx->Current.RasterColor,
                             ctx->Current.RasterTexCoords[0] );
   }
   else {
      ASSERT(ctx->RenderMode == GL_SELECT);
      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
   }
#endif

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

   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
      _mesa_flush(ctx);
   }
}
示例#21
0
void GLAPIENTRY
_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
		      GLenum format, GLenum type, GLsizei bufSize,
                      GLvoid *pixels )
{
   GLenum err = GL_NO_ERROR;
   struct gl_renderbuffer *rb;

   GET_CURRENT_CONTEXT(ctx);

   FLUSH_VERTICES(ctx, 0);
   FLUSH_CURRENT(ctx, 0);

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
                  width, height,
                  _mesa_lookup_enum_by_nr(format),
                  _mesa_lookup_enum_by_nr(type),
                  pixels);

   if (width < 0 || height < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE,
                   "glReadPixels(width=%d height=%d)", width, height );
      return;
   }

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

   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "glReadPixels(incomplete framebuffer)" );
      return;
   }

   rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
   if (rb == NULL) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glReadPixels(read buffer)");
      return;
   }

   /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
    * combinations of format and type that can be used.
    *
    * Technically, only two combinations are actually allowed:
    * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
    * preferred combination.  This code doesn't know what that preferred
    * combination is, and Mesa can handle anything valid.  Just work instead.
    */
   if (_mesa_is_gles(ctx)) {
      if (ctx->API == API_OPENGLES2 &&
          _mesa_is_color_format(format) &&
          _mesa_get_color_read_format(ctx) == format &&
          _mesa_get_color_read_type(ctx) == type) {
         err = GL_NO_ERROR;
      } else if (ctx->Version < 30) {
         err = _mesa_es_error_check_format_and_type(format, type, 2);
         if (err == GL_NO_ERROR) {
            if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
               err = GL_INVALID_OPERATION;
            }
         }
      } else {
         err = read_pixels_es3_error_check(format, type, rb);
      }

      if (err == GL_NO_ERROR && (format == GL_DEPTH_COMPONENT
          || format == GL_DEPTH_STENCIL)) {
         err = GL_INVALID_ENUM;
      }

      if (err != GL_NO_ERROR) {
         _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
                     _mesa_lookup_enum_by_nr(format),
                     _mesa_lookup_enum_by_nr(type));
         return;
      }
   }

   err = _mesa_error_check_format_and_type(ctx, format, type);
   if (err != GL_NO_ERROR) {
      _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
                  _mesa_lookup_enum_by_nr(format),
                  _mesa_lookup_enum_by_nr(type));
      return;
   }

   if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
       ctx->ReadBuffer->Visual.samples > 0) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
      return;
   }

   if (!_mesa_source_buffer_exists(ctx, format)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
      return;
   }

   /* Check that the destination format and source buffer are both
    * integer-valued or both non-integer-valued.
    */
   if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
      const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
      const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
      const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
      if (dstInteger != srcInteger) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glReadPixels(integer / non-integer format mismatch");
         return;
      }
   }

   if (width == 0 || height == 0)
      return; /* nothing to do */

   if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
                                  format, type, bufSize, pixels)) {
      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glReadPixels(out of bounds PBO access)");
      } else {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glReadnPixelsARB(out of bounds access:"
                     " bufSize (%d) is too small)", bufSize);
      }
      return;
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
       _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
      /* buffer is mapped - that's an error */
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
      return;
   }

   ctx->Driver.ReadPixels(ctx, x, y, width, height,
			  format, type, &ctx->Pack, pixels);
}
示例#22
0
static GLboolean
do_texture_drawpixels(GLcontext * ctx,
                      GLint x, GLint y,
                      GLsizei width, GLsizei height,
                      GLenum format, GLenum type,
                      const struct gl_pixelstore_attrib *unpack,
                      const GLvoid * pixels)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_region *dst = intel_drawbuf_region(intel);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
   GLuint src_offset;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      fprintf(stderr, "%s\n", __FUNCTION__);

   intelFlush(&intel->ctx);
   intel->vtbl.render_start(intel);
   intel->vtbl.emit_state(intel);

   if (!dst)
      return GL_FALSE;

   if (src) {
      if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
                                     format, type, pixels)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
         return GL_TRUE;
      }
   }
   else {
      /* PBO only for now:
       */
/*       _mesa_printf("%s - not PBO\n", __FUNCTION__); */
      return GL_FALSE;
   }

   /* There are a couple of things we can't do yet, one of which is
    * set the correct state for pixel operations when GL texturing is
    * enabled.  That's a pretty rare state and probably not worth the
    * effort.  A completely device-independent version of this may do
    * more.
    *
    * Similarly, we make no attempt to merge metaops processing with
    * an enabled fragment program, though it would certainly be
    * possible.
    */
   if (!intel_check_meta_tex_fragment_ops(ctx)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad GL fragment state for metaops texture\n",
                      __FUNCTION__);
      return GL_FALSE;
   }

   intel->vtbl.install_meta_state(intel);


   /* Is this true?  Also will need to turn depth testing on according
    * to state:
    */
   intel->vtbl.meta_no_stencil_write(intel);
   intel->vtbl.meta_no_depth_write(intel);

   /* Set the 3d engine to draw into the destination region:
    */
   intel->vtbl.meta_draw_region(intel, dst, intel->intelScreen->depth_region);

   intel->vtbl.meta_import_pixel_state(intel);

   src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
                                             format, type, 0, 0, 0);


   /* Setup the pbo up as a rectangular texture, if possible.
    *
    * TODO: This is almost always possible if the i915 fragment
    * program is adjusted to correctly swizzle the sampled colors.
    * The major exception is any 24bit texture, like RGB888, for which
    * there is no hardware support.  
    */
   if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, src_offset,
                                         rowLength, height, format, type)) {
      intel->vtbl.leave_meta_state(intel);
      return GL_FALSE;
   }

   intel->vtbl.meta_texture_blend_replace(intel);


   LOCK_HARDWARE(intel);

   if (intel->driDrawable->numClipRects) {
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
      GLint srcx, srcy;
      GLint dstx, dsty;

      dstx = x;
      dsty = dPriv->h - (y + height);

      srcx = 0;                 /* skiprows/pixels already done */
      srcy = 0;

      if (0) {
         const GLint orig_x = dstx;
         const GLint orig_y = dsty;

         if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
                                   &dstx, &dsty, &width, &height))
            goto out;

         srcx += dstx - orig_x;
         srcy += dsty - orig_y;
      }


      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("draw %d,%d %dx%d\n", dstx, dsty, width, height);

      /* Must use the regular cliprect mechanism in order to get the
       * drawing origin set correctly.  Otherwise scissor state is in
       * incorrect coordinate space.  Does this even need to hold the
       * lock???
       */
      intel_meta_draw_quad(intel,
                           dstx, dstx + width * ctx->Pixel.ZoomX,
                           dPriv->h - (y + height * ctx->Pixel.ZoomY),
                           dPriv->h - (y),
                           -ctx->Current.RasterPos[2] * .5,
                           0x00ff00ff,
                           srcx, srcx + width, srcy + height, srcy);
    out:
      intel->vtbl.leave_meta_state(intel);
      intel_batchbuffer_flush(intel->batch);
   }
   UNLOCK_HARDWARE(intel);
   return GL_TRUE;
}
示例#23
0
/**
 * Do error checking for a glGetTex(ture)Image() call.
 * \return GL_TRUE if any error, GL_FALSE if no errors.
 */
static GLboolean
getteximage_error_check(struct gl_context *ctx,
                        struct gl_texture_image *texImage,
                        GLenum target, GLint level,
                        GLenum format, GLenum type, GLsizei clientMemSize,
                        GLvoid *pixels, bool dsa)
{
   const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
   const GLuint dimensions = 2;
//   const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
   GLenum baseFormat;
   const char *suffix = dsa ? "ture" : "";

   assert(texImage);
   assert(maxLevels != 0);
   if (level < 0 || level >= maxLevels) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glGetTex%sImage(level out of range)", suffix);
      return GL_TRUE;
   }

   /*
    * Format and type checking has been moved up to GetnTexImage and
    * GetTextureImage so that it happens before getting the texImage object.
    */

   baseFormat = _mesa_get_format_base_format(texImage->TexFormat);

   /* Make sure the requested image format is compatible with the
    * texture's format.
    */
   if (_mesa_is_color_format(format)
       && !_mesa_is_color_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetTex%sImage(format mismatch)", suffix);
      return GL_TRUE;
   }
   else if (_mesa_is_depth_format(format)
            && !_mesa_is_depth_format(baseFormat)
            && !_mesa_is_depthstencil_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetTex%sImage(format mismatch)", suffix);
      return GL_TRUE;
   }
   else if (_mesa_is_stencil_format(format)
            && !ctx->Extensions.ARB_texture_stencil8) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glGetTex%sImage(format=GL_STENCIL_INDEX)", suffix);
      return GL_TRUE;
   }
   else if (_mesa_is_ycbcr_format(format)
            && !_mesa_is_ycbcr_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetTex%sImage(format mismatch)", suffix);
      return GL_TRUE;
   }
   else if (_mesa_is_depthstencil_format(format)
            && !_mesa_is_depthstencil_format(baseFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetTex%sImage(format mismatch)", suffix);
      return GL_TRUE;
   }
   else if (!_mesa_is_stencil_format(format) && _mesa_is_enum_format_integer(format) !=
            _mesa_is_format_integer(texImage->TexFormat)) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetTex%sImage(format mismatch)", suffix);
      return GL_TRUE;
   }

   if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
                                  texImage->Height, texImage->Depth,
                                  format, type, clientMemSize, pixels)) {
      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetTex%sImage(out of bounds PBO access)", suffix);
      } else {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "%s(out of bounds access:"
                     " bufSize (%d) is too small)",
                     dsa ? "glGetTextureImage" : "glGetnTexImageARB",
                     clientMemSize);
      }
      return GL_TRUE;
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      /* PBO should not be mapped */
      if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetTex%sImage(PBO is mapped)", suffix);
         return GL_TRUE;
      }
   }

   return GL_FALSE;
}
示例#24
0
void GLAPIENTRY
_mesa_GetPixelMapusv( GLenum map, GLushort *values )
{
   GET_CURRENT_CONTEXT(ctx);
   GLint mapsize, i;
   const struct gl_pixelmap *pm;

   ASSERT_OUTSIDE_BEGIN_END(ctx);

   pm = get_pixelmap(ctx, map);
   if (!pm) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
      return;
   }
   mapsize = pm ? pm->Size : 0;

   if (ctx->Pack.BufferObj->Name) {
      /* pack pixelmap into PBO */
      GLubyte *buf;
      /* Note, need to use DefaultPacking and Pack's buffer object */
      ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj;
      if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
                                     GL_INTENSITY, GL_UNSIGNED_SHORT,
                                     values)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetPixelMapusv(invalid PBO access)");
         return;
      }
      /* restore */
      ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
      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,
                     "glGetPixelMapusv(PBO is mapped)");
         return;
      }
      values = (GLushort *) ADD_POINTERS(buf, values);
   }
   else if (!values) {
      return;
   }

   switch (map) {
   /* special cases */
   case GL_PIXEL_MAP_I_TO_I:
      for (i = 0; i < mapsize; i++) {
         values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
      }
      break;
   case GL_PIXEL_MAP_S_TO_S:
      for (i = 0; i < mapsize; i++) {
         values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
      }
      break;
   default:
      for (i = 0; i < mapsize; i++) {
         CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
      }
   }

   if (ctx->Pack.BufferObj->Name) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                              ctx->Pack.BufferObj);
   }
}
示例#25
0
/* Pros:  
 *   - no waiting for idle before updating framebuffer.
 *   
 * Cons:
 *   - if upload is by memcpy, this may actually be slower than fallback path.
 *   - uploads the whole image even if destination is clipped
 *   
 * Need to benchmark.
 *
 * Given the questions about performance, implement for pbo's only.
 * This path is definitely a win if the pbo is already in agp.  If it
 * turns out otherwise, we can add the code necessary to upload client
 * data to agp space before performing the blit.  (Though it may turn
 * out to be better/simpler just to use the texture engine).
 */
static GLboolean
do_blit_drawpixels(GLcontext * ctx,
                   GLint x, GLint y,
                   GLsizei width, GLsizei height,
                   GLenum format, GLenum type,
                   const struct gl_pixelstore_attrib *unpack,
                   const GLvoid * pixels)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_region *dest = intel_drawbuf_region(intel);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset;
   GLuint rowLength;
   struct _DriFenceObject *fence = NULL;

   if (INTEL_DEBUG & DEBUG_PIXEL)
      _mesa_printf("%s\n", __FUNCTION__);


   if (!dest) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - no dest\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (src) {
      /* This validation should be done by core mesa:
       */
      if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
                                     format, type, pixels)) {
         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
         return GL_TRUE;
      }
   }
   else {
      /* PBO only for now:
       */
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - not PBO\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (!intel_check_blit_format(dest, format, type)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
      return GL_FALSE;
   }

   if (!intel_check_blit_fragment_ops(ctx)) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad GL fragment state for blitter\n",
                      __FUNCTION__);
      return GL_FALSE;
   }

   if (ctx->Pixel.ZoomX != 1.0F) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
      return GL_FALSE;
   }


   if (unpack->RowLength > 0)
      rowLength = unpack->RowLength;
   else
      rowLength = width;

   if (ctx->Pixel.ZoomY == -1.0F) {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
      return GL_FALSE;          /* later */
      y -= height;
   }
   else if (ctx->Pixel.ZoomY == 1.0F) {
      rowLength = -rowLength;
   }
   else {
      if (INTEL_DEBUG & DEBUG_PIXEL)
         _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
      return GL_FALSE;
   }

   src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
                                             format, type, 0, 0, 0);

   intelFlush(&intel->ctx);
   LOCK_HARDWARE(intel);

   if (intel->driDrawable->numClipRects) {
      __DRIdrawablePrivate *dPriv = intel->driDrawable;
      int nbox = dPriv->numClipRects;
      drm_clip_rect_t *box = dPriv->pClipRects;
      drm_clip_rect_t rect;
      drm_clip_rect_t dest_rect;
      struct _DriBufferObject *src_buffer =
         intel_bufferobj_buffer(intel, src, INTEL_READ);
      int i;

      dest_rect.x1 = dPriv->x + x;
      dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
      dest_rect.x2 = dest_rect.x1 + width;
      dest_rect.y2 = dest_rect.y1 + height;

      for (i = 0; i < nbox; i++) {
         if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
            continue;

         intelEmitCopyBlit(intel,
                           dest->cpp,
                           rowLength,
                           src_buffer, src_offset,
                           dest->pitch,
                           dest->buffer, 0,
                           rect.x1 - dest_rect.x1,
                           rect.y2 - dest_rect.y2,
                           rect.x1,
                           rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1,
			   ctx->Color.ColorLogicOpEnabled ?
			   ctx->Color.LogicOp : GL_COPY);
      }
      fence = intel_batchbuffer_flush(intel->batch);
      driFenceReference(fence);
   }
   UNLOCK_HARDWARE(intel);

   if (fence) {
      driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE);
      driFenceUnReference(fence);
   }

   if (INTEL_DEBUG & DEBUG_PIXEL)
      _mesa_printf("%s - DONE\n", __FUNCTION__);

   return GL_TRUE;
}