drawpix.c revision e6149fac64da1653a315687465a1d83bd8373612
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.0.1 4 * 5 * Copyright (C) 1999-2004 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 "colormac.h" 28#include "context.h" 29#include "drawpix.h" 30#include "feedback.h" 31#include "macros.h" 32#include "state.h" 33#include "mtypes.h" 34 35#if _HAVE_FULL_GL 36 37/* 38 * Execute glDrawPixels 39 */ 40void GLAPIENTRY 41_mesa_DrawPixels( GLsizei width, GLsizei height, 42 GLenum format, GLenum type, const GLvoid *pixels ) 43{ 44 GET_CURRENT_CONTEXT(ctx); 45 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 46 47 if (ctx->FragmentProgram.Enabled 48 && !ctx->FragmentProgram.Current->Instructions) { 49 _mesa_error(ctx, GL_INVALID_OPERATION, 50 "glDrawPixels (invalid fragment program)"); 51 return; 52 } 53 54 if (width < 0 || height < 0) { 55 _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); 56 return; 57 } 58 59 if (ctx->RenderMode==GL_RENDER) { 60 GLint x, y; 61 if (!pixels || !ctx->Current.RasterPosValid) { 62 return; 63 } 64 65 if (ctx->NewState) { 66 _mesa_update_state(ctx); 67 } 68 69 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ 70 x = IROUND(ctx->Current.RasterPos[0]); 71 y = IROUND(ctx->Current.RasterPos[1]); 72 73 ctx->OcclusionResult = GL_TRUE; 74 ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, 75 &ctx->Unpack, pixels); 76 } 77 else if (ctx->RenderMode==GL_FEEDBACK) { 78 /* Feedback the current raster pos info */ 79 if (ctx->Current.RasterPosValid) { 80 FLUSH_CURRENT( ctx, 0 ); 81 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 82 _mesa_feedback_vertex( ctx, 83 ctx->Current.RasterPos, 84 ctx->Current.RasterColor, 85 ctx->Current.RasterIndex, 86 ctx->Current.RasterTexCoords[0] ); 87 } 88 } 89 else if (ctx->RenderMode==GL_SELECT) { 90 if (ctx->Current.RasterPosValid) { 91 _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 92 } 93 } 94} 95 96void GLAPIENTRY 97_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, 98 GLenum type ) 99{ 100 GET_CURRENT_CONTEXT(ctx); 101 GLint destx, desty; 102 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 103 104 if (ctx->FragmentProgram.Enabled 105 && !ctx->FragmentProgram.Current->Instructions) { 106 _mesa_error(ctx, GL_INVALID_OPERATION, 107 "glCopyPixels (invalid fragment program)"); 108 return; 109 } 110 111 if (width < 0 || height < 0) { 112 _mesa_error( ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)" ); 113 return; 114 } 115 116 if (ctx->NewState) { 117 _mesa_update_state(ctx); 118 } 119 120 if (ctx->RenderMode==GL_RENDER) { 121 /* Destination of copy: */ 122 if (!ctx->Current.RasterPosValid) { 123 return; 124 } 125 126 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ 127 destx = IROUND(ctx->Current.RasterPos[0]); 128 desty = IROUND(ctx->Current.RasterPos[1]); 129 130 ctx->OcclusionResult = GL_TRUE; 131 132 ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, 133 type ); 134 } 135 else if (ctx->RenderMode == GL_FEEDBACK) { 136 if (ctx->Current.RasterPosValid) { 137 FLUSH_CURRENT( ctx, 0 ); 138 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); 139 _mesa_feedback_vertex( ctx, 140 ctx->Current.RasterPos, 141 ctx->Current.RasterColor, 142 ctx->Current.RasterIndex, 143 ctx->Current.RasterTexCoords[0] ); 144 } 145 } 146 else if (ctx->RenderMode == GL_SELECT) { 147 _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 148 } 149} 150 151#endif 152 153 154 155void GLAPIENTRY 156_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, 157 GLenum format, GLenum type, GLvoid *pixels ) 158{ 159 GET_CURRENT_CONTEXT(ctx); 160 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 161 162 if (width < 0 || height < 0) { 163 _mesa_error( ctx, GL_INVALID_VALUE, 164 "glReadPixels(width=%d height=%d)", width, height ); 165 return; 166 } 167 168 if (!pixels) { 169 _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" ); 170 return; 171 } 172 173 if (ctx->NewState) 174 _mesa_update_state(ctx); 175 176 ctx->Driver.ReadPixels(ctx, x, y, width, height, 177 format, type, &ctx->Pack, pixels); 178} 179 180 181 182 183 184void GLAPIENTRY 185_mesa_Bitmap( GLsizei width, GLsizei height, 186 GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, 187 const GLubyte *bitmap ) 188{ 189 GET_CURRENT_CONTEXT(ctx); 190 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 191 192 if (ctx->FragmentProgram.Enabled 193 && !ctx->FragmentProgram.Current->Instructions) { 194 _mesa_error(ctx, GL_INVALID_OPERATION, 195 "glBitmap (invalid fragment program)"); 196 return; 197 } 198 199 if (width < 0 || height < 0) { 200 _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); 201 return; 202 } 203 204 if (ctx->Current.RasterPosValid == GL_FALSE) { 205 return; /* do nothing */ 206 } 207 208 if (ctx->RenderMode==GL_RENDER) { 209 if (bitmap) { 210 /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ 211 GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig); 212 GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig); 213 214 if (ctx->NewState) { 215 _mesa_update_state(ctx); 216 } 217 218 ctx->OcclusionResult = GL_TRUE; 219 ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); 220 } 221 } 222#if _HAVE_FULL_GL 223 else if (ctx->RenderMode==GL_FEEDBACK) { 224 if (ctx->Current.RasterPosValid) { 225 FLUSH_CURRENT(ctx, 0); 226 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN ); 227 _mesa_feedback_vertex( ctx, 228 ctx->Current.RasterPos, 229 ctx->Current.RasterColor, 230 ctx->Current.RasterIndex, 231 ctx->Current.RasterTexCoords[0] ); 232 } 233 } 234 else { 235 ASSERT(ctx->RenderMode == GL_SELECT); 236 /* Bitmaps don't generate selection hits. See appendix B of 1.1 spec. */ 237 } 238#endif 239 240 /* update raster position */ 241 ctx->Current.RasterPos[0] += xmove; 242 ctx->Current.RasterPos[1] += ymove; 243} 244 245 246 247#if 0 /* experimental */ 248/* 249 * Execute glDrawDepthPixelsMESA(). This function accepts both a color 250 * image and depth (Z) image. Rasterization produces fragments with 251 * color and Z taken from these images. This function is intended for 252 * Z-compositing. Normally, this operation requires two glDrawPixels 253 * calls with stencil testing. 254 */ 255void GLAPIENTRY 256_mesa_DrawDepthPixelsMESA( GLsizei width, GLsizei height, 257 GLenum colorFormat, GLenum colorType, 258 const GLvoid *colors, 259 GLenum depthType, const GLvoid *depths ) 260{ 261 GET_CURRENT_CONTEXT(ctx); 262 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 263 264 if (width < 0 || height < 0) { 265 _mesa_error( ctx, GL_INVALID_VALUE, 266 "glDrawDepthPixelsMESA(width or height < 0" ); 267 return; 268 } 269 270 if (ctx->RenderMode==GL_RENDER) { 271 GLint x, y; 272 if (!colors || !depths || !ctx->Current.RasterPosValid) { 273 return; 274 } 275 276 if (ctx->NewState) { 277 _mesa_update_state(ctx); 278 } 279 280 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ 281 x = IROUND(ctx->Current.RasterPos[0]); 282 y = IROUND(ctx->Current.RasterPos[1]); 283 284 ctx->OcclusionResult = GL_TRUE; 285 ctx->Driver.DrawDepthPixelsMESA(ctx, x, y, width, height, 286 colorFormat, colorType, colors, 287 depthType, depths, &ctx->Unpack); 288 } 289 else if (ctx->RenderMode==GL_FEEDBACK) { 290 /* Feedback the current raster pos info */ 291 if (ctx->Current.RasterPosValid) { 292 FLUSH_CURRENT( ctx, 0 ); 293 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); 294 _mesa_feedback_vertex( ctx, 295 ctx->Current.RasterPos, 296 ctx->Current.RasterColor, 297 ctx->Current.RasterIndex, 298 ctx->Current.RasterTexCoords[0] ); 299 } 300 } 301 else if (ctx->RenderMode==GL_SELECT) { 302 if (ctx->Current.RasterPosValid) { 303 _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); 304 } 305 } 306} 307 308#endif 309