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