Пример #1
0
/*
 * Read R, G, B, A, RGB, L, or LA pixels.
 */
static void
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 = ctx->_ImageTransferState;
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct gl_renderbuffer *rb = fb->_ColorReadBuffer;

   if (!rb)
      return;

   if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) &&
       !_mesa_is_integer_format(format)) {
      transferOps |= IMAGE_CLAMP_BIT;
   }

   if (!transferOps) {
      /* Try the optimized paths first. */
      if (fast_read_rgba_pixels_memcpy(ctx, x, y, width, height,
				       format, type, pixels, packing,
				       transferOps)) {
	 return;
      }
   }

   slow_read_rgba_pixels(ctx, x, y, width, height,
			 format, type, pixels, packing, transferOps);
}
Пример #2
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);
}
Пример #3
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_integer_format(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);
}
Пример #4
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);
}
Пример #5
0
/**
 * Return a texture internalFormat for drawing/copying an image
 * of the given format and type.
 */
static GLenum
internal_format(struct gl_context *ctx, GLenum format, GLenum type)
{
   switch (format) {
   case GL_DEPTH_COMPONENT:
      return GL_DEPTH_COMPONENT;
   case GL_DEPTH_STENCIL:
      return GL_DEPTH_STENCIL;
   case GL_STENCIL_INDEX:
      return GL_STENCIL_INDEX;
   default:
      if (_mesa_is_integer_format(format)) {
         switch (type) {
         case GL_BYTE:
            return GL_RGBA8I;
         case GL_UNSIGNED_BYTE:
            return GL_RGBA8UI;
         case GL_SHORT:
            return GL_RGBA16I;
         case GL_UNSIGNED_SHORT:
            return GL_RGBA16UI;
         case GL_INT:
            return GL_RGBA32I;
         case GL_UNSIGNED_INT:
            return GL_RGBA32UI;
         default:
            assert(0 && "Unexpected type in internal_format()");
            return GL_RGBA_INTEGER;
         }
      }
      else {
         switch (type) {
         case GL_UNSIGNED_BYTE:
         case GL_UNSIGNED_INT_8_8_8_8:
         case GL_UNSIGNED_INT_8_8_8_8_REV:
         default:
            return GL_RGBA8;

         case GL_UNSIGNED_BYTE_3_3_2:
         case GL_UNSIGNED_BYTE_2_3_3_REV:
         case GL_UNSIGNED_SHORT_4_4_4_4:
         case GL_UNSIGNED_SHORT_4_4_4_4_REV:
            return GL_RGBA4;

         case GL_UNSIGNED_SHORT_5_6_5:
         case GL_UNSIGNED_SHORT_5_6_5_REV:
         case GL_UNSIGNED_SHORT_5_5_5_1:
         case GL_UNSIGNED_SHORT_1_5_5_5_REV:
            return GL_RGB5_A1;

         case GL_UNSIGNED_INT_10_10_10_2:
         case GL_UNSIGNED_INT_2_10_10_10_REV:
            return GL_RGB10_A2;

         case GL_UNSIGNED_SHORT:
         case GL_UNSIGNED_INT:
            return GL_RGBA16;

         case GL_BYTE:
            return
               ctx->Extensions.EXT_texture_snorm ? GL_RGBA8_SNORM : GL_RGBA8;

         case GL_SHORT:
         case GL_INT:
            return
               ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;

         case GL_HALF_FLOAT_ARB:
            return
               ctx->Extensions.ARB_texture_float ? GL_RGBA16F :
               ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;

         case GL_FLOAT:
         case GL_DOUBLE:
            return
               ctx->Extensions.ARB_texture_float ? GL_RGBA32F :
               ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;

         case GL_UNSIGNED_INT_5_9_9_9_REV:
            assert(ctx->Extensions.EXT_texture_shared_exponent);
            return GL_RGB9_E5;

         case GL_UNSIGNED_INT_10F_11F_11F_REV:
            assert(ctx->Extensions.EXT_packed_float);
            return GL_R11F_G11F_B10F;
         }
      }
   }
}