Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / main / drawpix.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.1
4  *
5  * Copyright (C) 1999-2008  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 "bufferobj.h"
28 #include "context.h"
29 #include "drawpix.h"
30 #include "enums.h"
31 #include "feedback.h"
32 #include "framebuffer.h"
33 #include "mfeatures.h"
34 #include "pbo.h"
35 #include "readpix.h"
36 #include "state.h"
37 #include "dispatch.h"
38
39
40 #if FEATURE_drawpix
41
42
43 /*
44  * Execute glDrawPixels
45  */
46 static void GLAPIENTRY
47 _mesa_DrawPixels( GLsizei width, GLsizei height,
48                   GLenum format, GLenum type, const GLvoid *pixels )
49 {
50    GET_CURRENT_CONTEXT(ctx);
51    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
52
53    if (MESA_VERBOSE & VERBOSE_API)
54       _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n",
55                   width, height,
56                   _mesa_lookup_enum_by_nr(format),
57                   _mesa_lookup_enum_by_nr(type),
58                   pixels,
59                   _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
60                   IROUND(ctx->Current.RasterPos[0]),
61                   IROUND(ctx->Current.RasterPos[1]));
62
63
64    if (width < 0 || height < 0) {
65       _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
66       return;
67    }
68
69    /* We're not using the current vertex program, and the driver may install
70     * its own.  Note: this may dirty some state.
71     */
72    _mesa_set_vp_override(ctx, GL_TRUE);
73
74    /* Note: this call does state validation */
75    if (!_mesa_valid_to_render(ctx, "glDrawPixels")) {
76       goto end;      /* the error code was recorded */
77    }
78
79    if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) {
80       goto end;      /* the error code was recorded */
81    }
82
83    if (!ctx->Current.RasterPosValid) {
84       goto end;  /* no-op, not an error */
85    }
86
87    if (ctx->RenderMode == GL_RENDER) {
88       if (width > 0 && height > 0) {
89          /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
90          GLint x = IROUND(ctx->Current.RasterPos[0]);
91          GLint y = IROUND(ctx->Current.RasterPos[1]);
92
93          if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
94             /* unpack from PBO */
95             if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
96                                            1, format, type, INT_MAX, pixels)) {
97                _mesa_error(ctx, GL_INVALID_OPERATION,
98                            "glDrawPixels(invalid PBO access)");
99                goto end;
100             }
101             if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
102                /* buffer is mapped - that's an error */
103                _mesa_error(ctx, GL_INVALID_OPERATION,
104                            "glDrawPixels(PBO is mapped)");
105                goto end;
106             }
107          }
108
109          ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
110                                 &ctx->Unpack, pixels);
111       }
112    }
113    else if (ctx->RenderMode == GL_FEEDBACK) {
114       /* Feedback the current raster pos info */
115       FLUSH_CURRENT( ctx, 0 );
116       _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
117       _mesa_feedback_vertex( ctx,
118                              ctx->Current.RasterPos,
119                              ctx->Current.RasterColor,
120                              ctx->Current.RasterTexCoords[0] );
121    }
122    else {
123       ASSERT(ctx->RenderMode == GL_SELECT);
124       /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
125    }
126
127 end:
128    _mesa_set_vp_override(ctx, GL_FALSE);
129 }
130
131
132 static void GLAPIENTRY
133 _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
134                   GLenum type )
135 {
136    GET_CURRENT_CONTEXT(ctx);
137    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
138
139    if (MESA_VERBOSE & VERBOSE_API)
140       _mesa_debug(ctx,
141                   "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n",
142                   srcx, srcy, width, height,
143                   _mesa_lookup_enum_by_nr(type),
144                   _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer),
145                   _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]),
146                   IROUND(ctx->Current.RasterPos[0]),
147                   IROUND(ctx->Current.RasterPos[1]));
148
149    if (width < 0 || height < 0) {
150       _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
151       return;
152    }
153
154    /* Note: more detailed 'type' checking is done by the
155     * _mesa_source/dest_buffer_exists() calls below.  That's where we
156     * check if the stencil buffer exists, etc.
157     */
158    if (type != GL_COLOR &&
159        type != GL_DEPTH &&
160        type != GL_STENCIL &&
161        type != GL_DEPTH_STENCIL) {
162       _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)",
163                   _mesa_lookup_enum_by_nr(type));
164       return;
165    }
166
167    /* We're not using the current vertex program, and the driver may install
168     * it's own.  Note: this may dirty some state.
169     */
170    _mesa_set_vp_override(ctx, GL_TRUE);
171
172    /* Note: this call does state validation */
173    if (!_mesa_valid_to_render(ctx, "glCopyPixels")) {
174       goto end;      /* the error code was recorded */
175    }
176
177    /* Check read buffer's status (draw buffer was already checked) */
178    if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
179       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
180                   "glCopyPixels(incomplete framebuffer)" );
181       goto end;
182    }
183
184    if (!_mesa_source_buffer_exists(ctx, type) ||
185        !_mesa_dest_buffer_exists(ctx, type)) {
186       _mesa_error(ctx, GL_INVALID_OPERATION,
187                   "glCopyPixels(missing source or dest buffer)");
188       goto end;
189    }
190
191    if (!ctx->Current.RasterPosValid || width == 0 || height == 0) {
192       goto end; /* no-op, not an error */
193    }
194
195    if (ctx->RenderMode == GL_RENDER) {
196       /* Round to satisfy conformance tests (matches SGI's OpenGL) */
197       if (width > 0 && height > 0) {
198          GLint destx = IROUND(ctx->Current.RasterPos[0]);
199          GLint desty = IROUND(ctx->Current.RasterPos[1]);
200          ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
201                                  type );
202       }
203    }
204    else if (ctx->RenderMode == GL_FEEDBACK) {
205       FLUSH_CURRENT( ctx, 0 );
206       _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
207       _mesa_feedback_vertex( ctx, 
208                              ctx->Current.RasterPos,
209                              ctx->Current.RasterColor,
210                              ctx->Current.RasterTexCoords[0] );
211    }
212    else {
213       ASSERT(ctx->RenderMode == GL_SELECT);
214       /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
215    }
216
217 end:
218    _mesa_set_vp_override(ctx, GL_FALSE);
219 }
220
221
222 static void GLAPIENTRY
223 _mesa_Bitmap( GLsizei width, GLsizei height,
224               GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
225               const GLubyte *bitmap )
226 {
227    GET_CURRENT_CONTEXT(ctx);
228    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
229
230    if (width < 0 || height < 0) {
231       _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
232       return;
233    }
234
235    if (!ctx->Current.RasterPosValid) {
236       return;    /* do nothing */
237    }
238
239    /* Note: this call does state validation */
240    if (!_mesa_valid_to_render(ctx, "glBitmap")) {
241       /* the error code was recorded */
242       return;
243    }
244
245    if (ctx->RenderMode == GL_RENDER) {
246       /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
247       if (width > 0 && height > 0) {
248          const GLfloat epsilon = 0.0001F;
249          GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
250          GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
251
252          if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
253             /* unpack from PBO */
254             if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
255                                            1, GL_COLOR_INDEX, GL_BITMAP,
256                                            INT_MAX, (const GLvoid *) bitmap)) {
257                _mesa_error(ctx, GL_INVALID_OPERATION,
258                            "glBitmap(invalid PBO access)");
259                return;
260             }
261             if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
262                /* buffer is mapped - that's an error */
263                _mesa_error(ctx, GL_INVALID_OPERATION,
264                            "glBitmap(PBO is mapped)");
265                return;
266             }
267          }
268
269          ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
270       }
271    }
272 #if _HAVE_FULL_GL
273    else if (ctx->RenderMode == GL_FEEDBACK) {
274       FLUSH_CURRENT(ctx, 0);
275       _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
276       _mesa_feedback_vertex( ctx,
277                              ctx->Current.RasterPos,
278                              ctx->Current.RasterColor,
279                              ctx->Current.RasterTexCoords[0] );
280    }
281    else {
282       ASSERT(ctx->RenderMode == GL_SELECT);
283       /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
284    }
285 #endif
286
287    /* update raster position */
288    ctx->Current.RasterPos[0] += xmove;
289    ctx->Current.RasterPos[1] += ymove;
290 }
291
292
293 void
294 _mesa_init_drawpix_dispatch(struct _glapi_table *disp)
295 {
296    SET_Bitmap(disp, _mesa_Bitmap);
297    SET_CopyPixels(disp, _mesa_CopyPixels);
298    SET_DrawPixels(disp, _mesa_DrawPixels);
299 }
300
301
302 #endif /* FEATURE_drawpix */