Support ARB_texture_env_crossbar. Changes the way programs are
[mesa.git] / src / mesa / main / drawpix.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.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
36 #if _HAVE_FULL_GL
37
38 /*
39 * Execute glDrawPixels
40 */
41 void 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->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
96
97 void GLAPIENTRY
98 _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
99 GLenum type )
100 {
101 GET_CURRENT_CONTEXT(ctx);
102 GLint destx, desty;
103 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
104
105 if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
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 /* _HAVE_FULL_GL */
152
153
154
155 void 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 (ctx->NewState)
169 _mesa_update_state(ctx);
170
171 ctx->Driver.ReadPixels(ctx, x, y, width, height,
172 format, type, &ctx->Pack, pixels);
173 }
174
175
176
177 void GLAPIENTRY
178 _mesa_Bitmap( GLsizei width, GLsizei height,
179 GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
180 const GLubyte *bitmap )
181 {
182 GET_CURRENT_CONTEXT(ctx);
183 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
184
185 if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
186 _mesa_error(ctx, GL_INVALID_OPERATION,
187 "glBitmap (invalid fragment program)");
188 return;
189 }
190
191 if (width < 0 || height < 0) {
192 _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
193 return;
194 }
195
196 if (ctx->Current.RasterPosValid == GL_FALSE) {
197 return; /* do nothing */
198 }
199
200 if (ctx->RenderMode==GL_RENDER) {
201 /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
202 GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig);
203 GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig);
204
205 if (ctx->NewState) {
206 _mesa_update_state(ctx);
207 }
208
209 ctx->OcclusionResult = GL_TRUE;
210 ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
211 }
212 #if _HAVE_FULL_GL
213 else if (ctx->RenderMode==GL_FEEDBACK) {
214 if (ctx->Current.RasterPosValid) {
215 FLUSH_CURRENT(ctx, 0);
216 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
217 _mesa_feedback_vertex( ctx,
218 ctx->Current.RasterPos,
219 ctx->Current.RasterColor,
220 ctx->Current.RasterIndex,
221 ctx->Current.RasterTexCoords[0] );
222 }
223 }
224 else {
225 ASSERT(ctx->RenderMode == GL_SELECT);
226 /* Bitmaps don't generate selection hits. See appendix B of 1.1 spec. */
227 }
228 #endif
229
230 /* update raster position */
231 ctx->Current.RasterPos[0] += xmove;
232 ctx->Current.RasterPos[1] += ymove;
233 }
234
235
236
237 #if 0 /* experimental */
238 /*
239 * Execute glDrawDepthPixelsMESA(). This function accepts both a color
240 * image and depth (Z) image. Rasterization produces fragments with
241 * color and Z taken from these images. This function is intended for
242 * Z-compositing. Normally, this operation requires two glDrawPixels
243 * calls with stencil testing.
244 */
245 void GLAPIENTRY
246 _mesa_DrawDepthPixelsMESA( GLsizei width, GLsizei height,
247 GLenum colorFormat, GLenum colorType,
248 const GLvoid *colors,
249 GLenum depthType, const GLvoid *depths )
250 {
251 GET_CURRENT_CONTEXT(ctx);
252 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
253
254 if (width < 0 || height < 0) {
255 _mesa_error( ctx, GL_INVALID_VALUE,
256 "glDrawDepthPixelsMESA(width or height < 0" );
257 return;
258 }
259
260 if (ctx->RenderMode==GL_RENDER) {
261 GLint x, y;
262 if (!colors || !depths || !ctx->Current.RasterPosValid) {
263 return;
264 }
265
266 if (ctx->NewState) {
267 _mesa_update_state(ctx);
268 }
269
270 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
271 x = IROUND(ctx->Current.RasterPos[0]);
272 y = IROUND(ctx->Current.RasterPos[1]);
273
274 ctx->OcclusionResult = GL_TRUE;
275 ctx->Driver.DrawDepthPixelsMESA(ctx, x, y, width, height,
276 colorFormat, colorType, colors,
277 depthType, depths, &ctx->Unpack);
278 }
279 else if (ctx->RenderMode==GL_FEEDBACK) {
280 /* Feedback the current raster pos info */
281 if (ctx->Current.RasterPosValid) {
282 FLUSH_CURRENT( ctx, 0 );
283 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
284 _mesa_feedback_vertex( ctx,
285 ctx->Current.RasterPos,
286 ctx->Current.RasterColor,
287 ctx->Current.RasterIndex,
288 ctx->Current.RasterTexCoords[0] );
289 }
290 }
291 else if (ctx->RenderMode==GL_SELECT) {
292 if (ctx->Current.RasterPosValid) {
293 _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
294 }
295 }
296 }
297
298 #endif