Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. #include "glheader.h"
  26. #include "imports.h"
  27. #include "bufferobj.h"
  28. #include "context.h"
  29. #include "drawpix.h"
  30. #include "enums.h"
  31. #include "feedback.h"
  32. #include "framebuffer.h"
  33. #include "image.h"
  34. #include "pbo.h"
  35. #include "state.h"
  36. #include "dispatch.h"
  37. #include "glformats.h"
  38. #include "fbobject.h"
  39.  
  40.  
  41. /*
  42.  * Execute glDrawPixels
  43.  */
  44. void GLAPIENTRY
  45. _mesa_DrawPixels( GLsizei width, GLsizei height,
  46.                   GLenum format, GLenum type, const GLvoid *pixels )
  47. {
  48.    GLenum err;
  49.    GET_CURRENT_CONTEXT(ctx);
  50.  
  51.    FLUSH_VERTICES(ctx, 0);
  52.  
  53.    if (MESA_VERBOSE & VERBOSE_API)
  54.       _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n",
  55.                   width, height,
  56.                   _mesa_lookup_enum_by_nr(format),
  57.                   _mesa_lookup_enum_by_nr(type),
  58.                   pixels,
  59.                   _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
  60.                   IROUND(ctx->Current.RasterPos[0]),
  61.                   IROUND(ctx->Current.RasterPos[1]));
  62.  
  63.  
  64.    if (width < 0 || height < 0) {
  65.       _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0)" );
  66.       return;
  67.    }
  68.  
  69.    /* We're not using the current vertex program, and the driver may install
  70.     * its own.  Note: this may dirty some state.
  71.     */
  72.    _mesa_set_vp_override(ctx, GL_TRUE);
  73.  
  74.    /* Note: this call does state validation */
  75.    if (!_mesa_valid_to_render(ctx, "glDrawPixels")) {
  76.       goto end;      /* the error code was recorded */
  77.    }
  78.  
  79.    /* GL 3.0 introduced a new restriction on glDrawPixels() over what was in
  80.     * GL_EXT_texture_integer.  From section 3.7.4 ("Rasterization of Pixel
  81.     * Rectangles) on page 151 of the GL 3.0 specification:
  82.     *
  83.     *     "If format contains integer components, as shown in table 3.6, an
  84.     *      INVALID OPERATION error is generated."
  85.     *
  86.     * Since DrawPixels rendering would be merely undefined if not an error (due
  87.     * to a lack of defined mapping from integer data to gl_Color fragment shader
  88.     * input), NVIDIA's implementation also just returns this error despite
  89.     * exposing GL_EXT_texture_integer, just return an error regardless.
  90.     */
  91.    if (_mesa_is_enum_format_integer(format)) {
  92.       _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(integer format)");
  93.       goto end;
  94.    }
  95.  
  96.    err = _mesa_error_check_format_and_type(ctx, format, type);
  97.    if (err != GL_NO_ERROR) {
  98.       _mesa_error(ctx, err, "glDrawPixels(invalid format %s and/or type %s)",
  99.                   _mesa_lookup_enum_by_nr(format),
  100.                   _mesa_lookup_enum_by_nr(type));
  101.       goto end;
  102.    }
  103.  
  104.    /* do special format-related checks */
  105.    switch (format) {
  106.    case GL_STENCIL_INDEX:
  107.    case GL_DEPTH_COMPONENT:
  108.    case GL_DEPTH_STENCIL_EXT:
  109.       /* these buffers must exist */
  110.       if (!_mesa_dest_buffer_exists(ctx, format)) {
  111.          _mesa_error(ctx, GL_INVALID_OPERATION,
  112.                      "glDrawPixels(missing deest buffer)");
  113.          goto end;
  114.       }
  115.       break;
  116.    case GL_COLOR_INDEX:
  117.       if (ctx->PixelMaps.ItoR.Size == 0 ||
  118.           ctx->PixelMaps.ItoG.Size == 0 ||
  119.           ctx->PixelMaps.ItoB.Size == 0) {
  120.          _mesa_error(ctx, GL_INVALID_OPERATION,
  121.                 "glDrawPixels(drawing color index pixels into RGB buffer)");
  122.          goto end;
  123.       }
  124.       break;
  125.    default:
  126.       /* for color formats it's not an error if the destination color
  127.        * buffer doesn't exist.
  128.        */
  129.       break;
  130.    }
  131.  
  132.    if (ctx->RasterDiscard) {
  133.       goto end;
  134.    }
  135.  
  136.    if (!ctx->Current.RasterPosValid) {
  137.       goto end;  /* no-op, not an error */
  138.    }
  139.  
  140.    if (ctx->RenderMode == GL_RENDER) {
  141.       if (width > 0 && height > 0) {
  142.          /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
  143.          GLint x = IROUND(ctx->Current.RasterPos[0]);
  144.          GLint y = IROUND(ctx->Current.RasterPos[1]);
  145.  
  146.          if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
  147.             /* unpack from PBO */
  148.             if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
  149.                                            1, format, type, INT_MAX, pixels)) {
  150.                _mesa_error(ctx, GL_INVALID_OPERATION,
  151.                            "glDrawPixels(invalid PBO access)");
  152.                goto end;
  153.             }
  154.             if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
  155.                /* buffer is mapped - that's an error */
  156.                _mesa_error(ctx, GL_INVALID_OPERATION,
  157.                            "glDrawPixels(PBO is mapped)");
  158.                goto end;
  159.             }
  160.          }
  161.  
  162.          ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
  163.                                 &ctx->Unpack, pixels);
  164.       }
  165.    }
  166.    else if (ctx->RenderMode == GL_FEEDBACK) {
  167.       /* Feedback the current raster pos info */
  168.       FLUSH_CURRENT( ctx, 0 );
  169.       _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
  170.       _mesa_feedback_vertex( ctx,
  171.                              ctx->Current.RasterPos,
  172.                              ctx->Current.RasterColor,
  173.                              ctx->Current.RasterTexCoords[0] );
  174.    }
  175.    else {
  176.       ASSERT(ctx->RenderMode == GL_SELECT);
  177.       /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
  178.    }
  179.  
  180. end:
  181.    _mesa_set_vp_override(ctx, GL_FALSE);
  182.  
  183.    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
  184.       _mesa_flush(ctx);
  185.    }
  186. }
  187.  
  188.  
  189. void GLAPIENTRY
  190. _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  191.                   GLenum type )
  192. {
  193.    GET_CURRENT_CONTEXT(ctx);
  194.  
  195.    FLUSH_VERTICES(ctx, 0);
  196.  
  197.    if (MESA_VERBOSE & VERBOSE_API)
  198.       _mesa_debug(ctx,
  199.                   "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n",
  200.                   srcx, srcy, width, height,
  201.                   _mesa_lookup_enum_by_nr(type),
  202.                   _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer),
  203.                   _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
  204.                   IROUND(ctx->Current.RasterPos[0]),
  205.                   IROUND(ctx->Current.RasterPos[1]));
  206.  
  207.    if (width < 0 || height < 0) {
  208.       _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
  209.       return;
  210.    }
  211.  
  212.    /* Note: more detailed 'type' checking is done by the
  213.     * _mesa_source/dest_buffer_exists() calls below.  That's where we
  214.     * check if the stencil buffer exists, etc.
  215.     */
  216.    if (type != GL_COLOR &&
  217.        type != GL_DEPTH &&
  218.        type != GL_STENCIL &&
  219.        type != GL_DEPTH_STENCIL) {
  220.       _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)",
  221.                   _mesa_lookup_enum_by_nr(type));
  222.       return;
  223.    }
  224.  
  225.    /* We're not using the current vertex program, and the driver may install
  226.     * it's own.  Note: this may dirty some state.
  227.     */
  228.    _mesa_set_vp_override(ctx, GL_TRUE);
  229.  
  230.    /* Note: this call does state validation */
  231.    if (!_mesa_valid_to_render(ctx, "glCopyPixels")) {
  232.       goto end;      /* the error code was recorded */
  233.    }
  234.  
  235.    /* Check read buffer's status (draw buffer was already checked) */
  236.    if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
  237.       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
  238.                   "glCopyPixels(incomplete framebuffer)" );
  239.       goto end;
  240.    }
  241.  
  242.    if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
  243.        ctx->ReadBuffer->Visual.samples > 0) {
  244.       _mesa_error(ctx, GL_INVALID_OPERATION,
  245.                   "glCopyPixels(multisample FBO)");
  246.       goto end;
  247.    }
  248.  
  249.    if (!_mesa_source_buffer_exists(ctx, type) ||
  250.        !_mesa_dest_buffer_exists(ctx, type)) {
  251.       _mesa_error(ctx, GL_INVALID_OPERATION,
  252.                   "glCopyPixels(missing source or dest buffer)");
  253.       goto end;
  254.    }
  255.  
  256.    if (ctx->RasterDiscard) {
  257.       goto end;
  258.    }
  259.  
  260.    if (!ctx->Current.RasterPosValid || width == 0 || height == 0) {
  261.       goto end; /* no-op, not an error */
  262.    }
  263.  
  264.    if (ctx->RenderMode == GL_RENDER) {
  265.       /* Round to satisfy conformance tests (matches SGI's OpenGL) */
  266.       if (width > 0 && height > 0) {
  267.          GLint destx = IROUND(ctx->Current.RasterPos[0]);
  268.          GLint desty = IROUND(ctx->Current.RasterPos[1]);
  269.          ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
  270.                                  type );
  271.       }
  272.    }
  273.    else if (ctx->RenderMode == GL_FEEDBACK) {
  274.       FLUSH_CURRENT( ctx, 0 );
  275.       _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
  276.       _mesa_feedback_vertex( ctx,
  277.                              ctx->Current.RasterPos,
  278.                              ctx->Current.RasterColor,
  279.                              ctx->Current.RasterTexCoords[0] );
  280.    }
  281.    else {
  282.       ASSERT(ctx->RenderMode == GL_SELECT);
  283.       /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
  284.    }
  285.  
  286. end:
  287.    _mesa_set_vp_override(ctx, GL_FALSE);
  288.  
  289.    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
  290.       _mesa_flush(ctx);
  291.    }
  292. }
  293.  
  294.  
  295. void GLAPIENTRY
  296. _mesa_Bitmap( GLsizei width, GLsizei height,
  297.               GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
  298.               const GLubyte *bitmap )
  299. {
  300.    GET_CURRENT_CONTEXT(ctx);
  301.  
  302.    FLUSH_VERTICES(ctx, 0);
  303.  
  304.    if (width < 0 || height < 0) {
  305.       _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
  306.       return;
  307.    }
  308.  
  309.    if (!ctx->Current.RasterPosValid) {
  310.       return;    /* do nothing */
  311.    }
  312.  
  313.    /* Note: this call does state validation */
  314.    if (!_mesa_valid_to_render(ctx, "glBitmap")) {
  315.       /* the error code was recorded */
  316.       return;
  317.    }
  318.  
  319.    if (ctx->RasterDiscard)
  320.       return;
  321.  
  322.    if (ctx->RenderMode == GL_RENDER) {
  323.       /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
  324.       if (width > 0 && height > 0) {
  325.          const GLfloat epsilon = 0.0001F;
  326.          GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
  327.          GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
  328.  
  329.          if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
  330.             /* unpack from PBO */
  331.             if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
  332.                                            1, GL_COLOR_INDEX, GL_BITMAP,
  333.                                            INT_MAX, (const GLvoid *) bitmap)) {
  334.                _mesa_error(ctx, GL_INVALID_OPERATION,
  335.                            "glBitmap(invalid PBO access)");
  336.                return;
  337.             }
  338.             if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
  339.                /* buffer is mapped - that's an error */
  340.                _mesa_error(ctx, GL_INVALID_OPERATION,
  341.                            "glBitmap(PBO is mapped)");
  342.                return;
  343.             }
  344.          }
  345.  
  346.          ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
  347.       }
  348.    }
  349.    else if (ctx->RenderMode == GL_FEEDBACK) {
  350.       FLUSH_CURRENT(ctx, 0);
  351.       _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
  352.       _mesa_feedback_vertex( ctx,
  353.                              ctx->Current.RasterPos,
  354.                              ctx->Current.RasterColor,
  355.                              ctx->Current.RasterTexCoords[0] );
  356.    }
  357.    else {
  358.       ASSERT(ctx->RenderMode == GL_SELECT);
  359.       /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
  360.    }
  361.  
  362.    /* update raster position */
  363.    ctx->Current.RasterPos[0] += xmove;
  364.    ctx->Current.RasterPos[1] += ymove;
  365.  
  366.    if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
  367.       _mesa_flush(ctx);
  368.    }
  369. }
  370.