drawpix.c revision db61b9ce39bccc43140357652ceb78baaf2aea44
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 "readpix.h" 35#include "state.h" 36#include "dispatch.h" 37 38 39#if FEATURE_drawpix 40 41 42/* 43 * Execute glDrawPixels 44 */ 45static void GLAPIENTRY 46_mesa_DrawPixels( GLsizei width, GLsizei height, 47 GLenum format, GLenum type, const GLvoid *pixels ) 48{ 49 GET_CURRENT_CONTEXT(ctx); 50 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 51 52 if (width < 0 || height < 0) { 53 _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); 54 return; 55 } 56 57 /* We're not using the current vertex program, and the driver may install 58 * its own. Note: this may dirty some state. 59 */ 60 _mesa_set_vp_override(ctx, GL_TRUE); 61 62 /* Note: this call does state validation */ 63 if (!_mesa_valid_to_render(ctx, "glDrawPixels")) { 64 goto end; /* the error code was recorded */ 65 } 66 67 if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) { 68 goto end; /* the error code was recorded */ 69 } 70 71 if (!ctx->Current.RasterPosValid) { 72 goto end; /* no-op, not an error */ 73 } 74 75 if (ctx->RenderMode == GL_RENDER) { 76 if (width > 0 && height > 0) { 77 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ 78 GLint x = IROUND(ctx->Current.RasterPos[0]); 79 GLint y = IROUND(ctx->Current.RasterPos[1]); 80 81 if (ctx->Unpack.BufferObj->Name) { 82 /* unpack from PBO */ 83 if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, 84 format, type, pixels)) { 85 _mesa_error(ctx, GL_INVALID_OPERATION, 86 "glDrawPixels(invalid PBO access)"); 87 goto end; 88 } 89 if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { 90 /* buffer is mapped - that's an error */ 91 _mesa_error(ctx, GL_INVALID_OPERATION, 92 "glDrawPixels(PBO is mapped)"); 93 goto end; 94 } 95 } 96 97 ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, 98 &ctx->Unpack, pixels); 99 } 100 } 101 else if (ctx->RenderMode == GL_FEEDBACK) { 102 /* Feedback the current raster pos info */ 103 FLUSH_CURRENT( ctx, 0 ); 104 _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 105 _mesa_feedback_vertex( ctx, 106 ctx->Current.RasterPos, 107 ctx->Current.RasterColor, 108 ctx->Current.RasterTexCoords[0] ); 109 } 110 else { 111 ASSERT(ctx->RenderMode == GL_SELECT); 112 /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ 113 } 114 115end: 116 _mesa_set_vp_override(ctx, GL_FALSE); 117} 118 119 120static void GLAPIENTRY 121_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, 122 GLenum type ) 123{ 124 GET_CURRENT_CONTEXT(ctx); 125 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 126 127 if (width < 0 || height < 0) { 128 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); 129 return; 130 } 131 132 /* Note: more detailed 'type' checking is done by the 133 * _mesa_source/dest_buffer_exists() calls below. That's where we 134 * check if the stencil buffer exists, etc. 135 */ 136 if (type != GL_COLOR && 137 type != GL_DEPTH && 138 type != GL_STENCIL && 139 type != GL_DEPTH_STENCIL) { 140 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)", 141 _mesa_lookup_enum_by_nr(type)); 142 return; 143 } 144 145 /* We're not using the current vertex program, and the driver may install 146 * it's own. Note: this may dirty some state. 147 */ 148 _mesa_set_vp_override(ctx, GL_TRUE); 149 150 /* Note: this call does state validation */ 151 if (!_mesa_valid_to_render(ctx, "glCopyPixels")) { 152 goto end; /* the error code was recorded */ 153 } 154 155 /* Check read buffer's status (draw buffer was already checked) */ 156 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 157 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 158 "glCopyPixels(incomplete framebuffer)" ); 159 goto end; 160 } 161 162 if (!_mesa_source_buffer_exists(ctx, type) || 163 !_mesa_dest_buffer_exists(ctx, type)) { 164 _mesa_error(ctx, GL_INVALID_OPERATION, 165 "glCopyPixels(missing source or dest buffer)"); 166 goto end; 167 } 168 169 if (!ctx->Current.RasterPosValid || width ==0 || height == 0) { 170 goto end; /* no-op, not an error */ 171 } 172 173 if (ctx->RenderMode == GL_RENDER) { 174 /* Round to satisfy conformance tests (matches SGI's OpenGL) */ 175 if (width > 0 && height > 0) { 176 GLint destx = IROUND(ctx->Current.RasterPos[0]); 177 GLint desty = IROUND(ctx->Current.RasterPos[1]); 178 ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, 179 type ); 180 } 181 } 182 else if (ctx->RenderMode == GL_FEEDBACK) { 183 FLUSH_CURRENT( ctx, 0 ); 184 _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); 185 _mesa_feedback_vertex( ctx, 186 ctx->Current.RasterPos, 187 ctx->Current.RasterColor, 188 ctx->Current.RasterTexCoords[0] ); 189 } 190 else { 191 ASSERT(ctx->RenderMode == GL_SELECT); 192 /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ 193 } 194 195end: 196 _mesa_set_vp_override(ctx, GL_FALSE); 197} 198 199 200static void GLAPIENTRY 201_mesa_Bitmap( GLsizei width, GLsizei height, 202 GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, 203 const GLubyte *bitmap ) 204{ 205 GET_CURRENT_CONTEXT(ctx); 206 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 207 208 if (width < 0 || height < 0) { 209 _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); 210 return; 211 } 212 213 if (!ctx->Current.RasterPosValid) { 214 return; /* do nothing */ 215 } 216 217 /* Note: this call does state validation */ 218 if (!_mesa_valid_to_render(ctx, "glBitmap")) { 219 /* the error code was recorded */ 220 return; 221 } 222 223 if (ctx->RenderMode == GL_RENDER) { 224 /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ 225 if (width > 0 && height > 0) { 226 const GLfloat epsilon = 0.0001F; 227 GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig); 228 GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig); 229 230 if (ctx->Unpack.BufferObj->Name) { 231 /* unpack from PBO */ 232 if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, 233 GL_COLOR_INDEX, GL_BITMAP, 234 (GLvoid *) bitmap)) { 235 _mesa_error(ctx, GL_INVALID_OPERATION, 236 "glBitmap(invalid PBO access)"); 237 return; 238 } 239 if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { 240 /* buffer is mapped - that's an error */ 241 _mesa_error(ctx, GL_INVALID_OPERATION, 242 "glBitmap(PBO is mapped)"); 243 return; 244 } 245 } 246 247 ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); 248 } 249 } 250#if _HAVE_FULL_GL 251 else if (ctx->RenderMode == GL_FEEDBACK) { 252 FLUSH_CURRENT(ctx, 0); 253 _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN ); 254 _mesa_feedback_vertex( ctx, 255 ctx->Current.RasterPos, 256 ctx->Current.RasterColor, 257 ctx->Current.RasterTexCoords[0] ); 258 } 259 else { 260 ASSERT(ctx->RenderMode == GL_SELECT); 261 /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ 262 } 263#endif 264 265 /* update raster position */ 266 ctx->Current.RasterPos[0] += xmove; 267 ctx->Current.RasterPos[1] += ymove; 268} 269 270 271void 272_mesa_init_drawpix_dispatch(struct _glapi_table *disp) 273{ 274 SET_Bitmap(disp, _mesa_Bitmap); 275 SET_CopyPixels(disp, _mesa_CopyPixels); 276 SET_DrawPixels(disp, _mesa_DrawPixels); 277} 278 279 280#endif /* FEATURE_drawpix */ 281