improved solve_plane_chan() (Evgeny Kotsuba)
[mesa.git] / src / mesa / main / drawpix.c
1 /* $Id: drawpix.c,v 1.63 2002/10/24 23:57:20 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #include "glheader.h"
28 #include "imports.h"
29 #include "colormac.h"
30 #include "context.h"
31 #include "drawpix.h"
32 #include "feedback.h"
33 #include "macros.h"
34 #include "mmath.h"
35 #include "state.h"
36 #include "mtypes.h"
37
38
39 /*
40 * Execute glDrawPixels
41 */
42 void
43 _mesa_DrawPixels( GLsizei width, GLsizei height,
44 GLenum format, GLenum type, const GLvoid *pixels )
45 {
46 GET_CURRENT_CONTEXT(ctx);
47 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
48
49 if (width < 0 || height < 0) {
50 _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
51 return;
52 }
53
54 if (ctx->RenderMode==GL_RENDER) {
55 GLint x, y;
56 if (!pixels || !ctx->Current.RasterPosValid) {
57 return;
58 }
59
60 if (ctx->NewState) {
61 _mesa_update_state(ctx);
62 }
63
64 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
65 x = IROUND(ctx->Current.RasterPos[0]);
66 y = IROUND(ctx->Current.RasterPos[1]);
67
68 ctx->OcclusionResult = GL_TRUE;
69 ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
70 &ctx->Unpack, pixels);
71 }
72 else if (ctx->RenderMode==GL_FEEDBACK) {
73 /* Feedback the current raster pos info */
74 if (ctx->Current.RasterPosValid) {
75 FLUSH_CURRENT( ctx, 0 );
76 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
77 _mesa_feedback_vertex( ctx,
78 ctx->Current.RasterPos,
79 ctx->Current.RasterColor,
80 ctx->Current.RasterIndex,
81 ctx->Current.RasterTexCoords[0] );
82 }
83 }
84 else if (ctx->RenderMode==GL_SELECT) {
85 if (ctx->Current.RasterPosValid) {
86 _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
87 }
88 }
89 }
90
91
92
93 void
94 _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
95 GLenum format, GLenum type, GLvoid *pixels )
96 {
97 GET_CURRENT_CONTEXT(ctx);
98 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
99
100 if (width < 0 || height < 0) {
101 _mesa_error( ctx, GL_INVALID_VALUE,
102 "glReadPixels(width=%d height=%d)", width, height );
103 return;
104 }
105
106 if (!pixels) {
107 _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
108 return;
109 }
110
111 if (ctx->NewState)
112 _mesa_update_state(ctx);
113
114 ctx->Driver.ReadPixels(ctx, x, y, width, height,
115 format, type, &ctx->Pack, pixels);
116 }
117
118
119
120 void
121 _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
122 GLenum type )
123 {
124 GET_CURRENT_CONTEXT(ctx);
125 GLint destx, desty;
126 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
127
128 if (width < 0 || height < 0) {
129 _mesa_error( ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)" );
130 return;
131 }
132
133 if (ctx->NewState) {
134 _mesa_update_state(ctx);
135 }
136
137 if (ctx->RenderMode==GL_RENDER) {
138 /* Destination of copy: */
139 if (!ctx->Current.RasterPosValid) {
140 return;
141 }
142
143 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
144 destx = IROUND(ctx->Current.RasterPos[0]);
145 desty = IROUND(ctx->Current.RasterPos[1]);
146
147 ctx->OcclusionResult = GL_TRUE;
148
149 ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
150 type );
151 }
152 else if (ctx->RenderMode == GL_FEEDBACK) {
153 if (ctx->Current.RasterPosValid) {
154 FLUSH_CURRENT( ctx, 0 );
155 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
156 _mesa_feedback_vertex( ctx,
157 ctx->Current.RasterPos,
158 ctx->Current.RasterColor,
159 ctx->Current.RasterIndex,
160 ctx->Current.RasterTexCoords[0] );
161 }
162 }
163 else if (ctx->RenderMode == GL_SELECT) {
164 _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
165 }
166 }
167
168
169
170 void
171 _mesa_Bitmap( GLsizei width, GLsizei height,
172 GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
173 const GLubyte *bitmap )
174 {
175 GET_CURRENT_CONTEXT(ctx);
176 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
177
178 if (width < 0 || height < 0) {
179 _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
180 return;
181 }
182
183 if (ctx->Current.RasterPosValid == GL_FALSE) {
184 return; /* do nothing */
185 }
186
187 if (ctx->RenderMode==GL_RENDER) {
188 if (bitmap) {
189 /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
190 GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig);
191 GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig);
192
193 if (ctx->NewState) {
194 _mesa_update_state(ctx);
195 }
196
197 ctx->OcclusionResult = GL_TRUE;
198 ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
199 }
200 }
201 else if (ctx->RenderMode==GL_FEEDBACK) {
202 if (ctx->Current.RasterPosValid) {
203 FLUSH_CURRENT(ctx, 0);
204 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
205 _mesa_feedback_vertex( ctx,
206 ctx->Current.RasterPos,
207 ctx->Current.RasterColor,
208 ctx->Current.RasterIndex,
209 ctx->Current.RasterTexCoords[0] );
210 }
211 }
212 else if (ctx->RenderMode==GL_SELECT) {
213 /* Bitmaps don't generate selection hits. See appendix B of 1.1 spec. */
214 }
215
216 /* update raster position */
217 ctx->Current.RasterPos[0] += xmove;
218 ctx->Current.RasterPos[1] += ymove;
219 }
220
221
222
223 #if 0 /* experimental */
224 /*
225 * Execute glDrawDepthPixelsMESA(). This function accepts both a color
226 * image and depth (Z) image. Rasterization produces fragments with
227 * color and Z taken from these images. This function is intended for
228 * Z-compositing. Normally, this operation requires two glDrawPixels
229 * calls with stencil testing.
230 */
231 void
232 _mesa_DrawDepthPixelsMESA( GLsizei width, GLsizei height,
233 GLenum colorFormat, GLenum colorType,
234 const GLvoid *colors,
235 GLenum depthType, const GLvoid *depths )
236 {
237 GET_CURRENT_CONTEXT(ctx);
238 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
239
240 if (width < 0 || height < 0) {
241 _mesa_error( ctx, GL_INVALID_VALUE,
242 "glDrawDepthPixelsMESA(width or height < 0" );
243 return;
244 }
245
246 if (ctx->RenderMode==GL_RENDER) {
247 GLint x, y;
248 if (!colors || !depths || !ctx->Current.RasterPosValid) {
249 return;
250 }
251
252 if (ctx->NewState) {
253 _mesa_update_state(ctx);
254 }
255
256 /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
257 x = IROUND(ctx->Current.RasterPos[0]);
258 y = IROUND(ctx->Current.RasterPos[1]);
259
260 ctx->OcclusionResult = GL_TRUE;
261 ctx->Driver.DrawDepthPixelsMESA(ctx, x, y, width, height,
262 colorFormat, colorType, colors,
263 depthType, depths, &ctx->Unpack);
264 }
265 else if (ctx->RenderMode==GL_FEEDBACK) {
266 /* Feedback the current raster pos info */
267 if (ctx->Current.RasterPosValid) {
268 FLUSH_CURRENT( ctx, 0 );
269 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
270 _mesa_feedback_vertex( ctx,
271 ctx->Current.RasterPos,
272 ctx->Current.RasterColor,
273 ctx->Current.RasterIndex,
274 ctx->Current.RasterTexCoords[0] );
275 }
276 }
277 else if (ctx->RenderMode==GL_SELECT) {
278 if (ctx->Current.RasterPosValid) {
279 _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
280 }
281 }
282 }
283
284 #endif