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