drawpix.c revision e4852ae4d24396daa323652023655fb3b6456ff5
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 "mfeatures.h" 34#include "pbo.h" 35#include "readpix.h" 36#include "state.h" 37#include "dispatch.h" 38 39 40#if FEATURE_drawpix 41 42 43/* 44 * Execute glDrawPixels 45 */ 46static void GLAPIENTRY 47_mesa_DrawPixels( GLsizei width, GLsizei height, 48 GLenum format, GLenum type, const GLvoid *pixels ) 49{ 50 GET_CURRENT_CONTEXT(ctx); 51 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 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 if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) { 80 goto end; /* the error code was recorded */ 81 } 82 83 if (!ctx->Current.RasterPosValid) { 84 goto end; /* no-op, not an error */ 85 } 86 87 if (ctx->RenderMode == GL_RENDER) { 88 if (width > 0 && height > 0) { 89 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ 90 GLint x = IROUND(ctx->Current.RasterPos[0]); 91 GLint y = IROUND(ctx->Current.RasterPos[1]); 92 93 if (ctx->Unpack.BufferObj->Name) { 94 /* unpack from PBO */ 95 if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, 96 format, type, pixels)) { 97 _mesa_error(ctx, GL_INVALID_OPERATION, 98 "glDrawPixels(invalid PBO access)"); 99 goto end; 100 } 101 if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { 102 /* buffer is mapped - that's an error */ 103 _mesa_error(ctx, GL_INVALID_OPERATION, 104 "glDrawPixels(PBO is mapped)"); 105 goto end; 106 } 107 } 108 109 ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, 110 &ctx->Unpack, pixels); 111 } 112 } 113 else if (ctx->RenderMode == GL_FEEDBACK) { 114 /* Feedback the current raster pos info */ 115 FLUSH_CURRENT( ctx, 0 ); 116 _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 117 _mesa_feedback_vertex( ctx, 118 ctx->Current.RasterPos, 119 ctx->Current.RasterColor, 120 ctx->Current.RasterTexCoords[0] ); 121 } 122 else { 123 ASSERT(ctx->RenderMode == GL_SELECT); 124 /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ 125 } 126 127end: 128 _mesa_set_vp_override(ctx, GL_FALSE); 129} 130 131 132static void GLAPIENTRY 133_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, 134 GLenum type ) 135{ 136 GET_CURRENT_CONTEXT(ctx); 137 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 138 139 if (MESA_VERBOSE & VERBOSE_API) 140 _mesa_debug(ctx, 141 "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n", 142 srcx, srcy, width, height, 143 _mesa_lookup_enum_by_nr(type), 144 _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer), 145 _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), 146 IROUND(ctx->Current.RasterPos[0]), 147 IROUND(ctx->Current.RasterPos[1])); 148 149 if (width < 0 || height < 0) { 150 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); 151 return; 152 } 153 154 /* Note: more detailed 'type' checking is done by the 155 * _mesa_source/dest_buffer_exists() calls below. That's where we 156 * check if the stencil buffer exists, etc. 157 */ 158 if (type != GL_COLOR && 159 type != GL_DEPTH && 160 type != GL_STENCIL && 161 type != GL_DEPTH_STENCIL) { 162 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)", 163 _mesa_lookup_enum_by_nr(type)); 164 return; 165 } 166 167 /* We're not using the current vertex program, and the driver may install 168 * it's own. Note: this may dirty some state. 169 */ 170 _mesa_set_vp_override(ctx, GL_TRUE); 171 172 /* Note: this call does state validation */ 173 if (!_mesa_valid_to_render(ctx, "glCopyPixels")) { 174 goto end; /* the error code was recorded */ 175 } 176 177 /* Check read buffer's status (draw buffer was already checked) */ 178 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 179 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 180 "glCopyPixels(incomplete framebuffer)" ); 181 goto end; 182 } 183 184 if (!_mesa_source_buffer_exists(ctx, type) || 185 !_mesa_dest_buffer_exists(ctx, type)) { 186 _mesa_error(ctx, GL_INVALID_OPERATION, 187 "glCopyPixels(missing source or dest buffer)"); 188 goto end; 189 } 190 191 if (!ctx->Current.RasterPosValid || width == 0 || height == 0) { 192 goto end; /* no-op, not an error */ 193 } 194 195 if (ctx->RenderMode == GL_RENDER) { 196 /* Round to satisfy conformance tests (matches SGI's OpenGL) */ 197 if (width > 0 && height > 0) { 198 GLint destx = IROUND(ctx->Current.RasterPos[0]); 199 GLint desty = IROUND(ctx->Current.RasterPos[1]); 200 ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, 201 type ); 202 } 203 } 204 else if (ctx->RenderMode == GL_FEEDBACK) { 205 FLUSH_CURRENT( ctx, 0 ); 206 _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); 207 _mesa_feedback_vertex( ctx, 208 ctx->Current.RasterPos, 209 ctx->Current.RasterColor, 210 ctx->Current.RasterTexCoords[0] ); 211 } 212 else { 213 ASSERT(ctx->RenderMode == GL_SELECT); 214 /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ 215 } 216 217end: 218 _mesa_set_vp_override(ctx, GL_FALSE); 219} 220 221 222static void GLAPIENTRY 223_mesa_Bitmap( GLsizei width, GLsizei height, 224 GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, 225 const GLubyte *bitmap ) 226{ 227 GET_CURRENT_CONTEXT(ctx); 228 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 229 230 if (width < 0 || height < 0) { 231 _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); 232 return; 233 } 234 235 if (!ctx->Current.RasterPosValid) { 236 return; /* do nothing */ 237 } 238 239 /* Note: this call does state validation */ 240 if (!_mesa_valid_to_render(ctx, "glBitmap")) { 241 /* the error code was recorded */ 242 return; 243 } 244 245 if (ctx->RenderMode == GL_RENDER) { 246 /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ 247 if (width > 0 && height > 0) { 248 const GLfloat epsilon = 0.0001F; 249 GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig); 250 GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig); 251 252 if (ctx->Unpack.BufferObj->Name) { 253 /* unpack from PBO */ 254 if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, 255 GL_COLOR_INDEX, GL_BITMAP, 256 (GLvoid *) bitmap)) { 257 _mesa_error(ctx, GL_INVALID_OPERATION, 258 "glBitmap(invalid PBO access)"); 259 return; 260 } 261 if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { 262 /* buffer is mapped - that's an error */ 263 _mesa_error(ctx, GL_INVALID_OPERATION, 264 "glBitmap(PBO is mapped)"); 265 return; 266 } 267 } 268 269 ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); 270 } 271 } 272#if _HAVE_FULL_GL 273 else if (ctx->RenderMode == GL_FEEDBACK) { 274 FLUSH_CURRENT(ctx, 0); 275 _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_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#endif 286 287 /* update raster position */ 288 ctx->Current.RasterPos[0] += xmove; 289 ctx->Current.RasterPos[1] += ymove; 290} 291 292 293void 294_mesa_init_drawpix_dispatch(struct _glapi_table *disp) 295{ 296 SET_Bitmap(disp, _mesa_Bitmap); 297 SET_CopyPixels(disp, _mesa_CopyPixels); 298 SET_DrawPixels(disp, _mesa_DrawPixels); 299} 300 301 302#endif /* FEATURE_drawpix */ 303