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