Merge branch 'mesa_7_5_branch'
[mesa.git] / src / mesa / drivers / dri / intel / intel_pixel.c
1 /**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portionsalloc
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "main/enums.h"
29 #include "main/state.h"
30 #include "main/bufferobj.h"
31 #include "main/context.h"
32 #include "main/enable.h"
33 #include "main/matrix.h"
34 #include "main/texstate.h"
35 #include "main/varray.h"
36 #include "main/viewport.h"
37 #include "swrast/swrast.h"
38 #include "shader/arbprogram.h"
39 #include "shader/program.h"
40
41 #include "intel_context.h"
42 #include "intel_pixel.h"
43 #include "intel_regions.h"
44
45 #define FILE_DEBUG_FLAG DEBUG_PIXEL
46
47 static GLenum
48 effective_func(GLenum func, GLboolean src_alpha_is_one)
49 {
50 if (src_alpha_is_one) {
51 if (func == GL_SRC_ALPHA)
52 return GL_ONE;
53 if (func == GL_ONE_MINUS_SRC_ALPHA)
54 return GL_ZERO;
55 }
56
57 return func;
58 }
59
60 /**
61 * Check if any fragment operations are in effect which might effect
62 * glDraw/CopyPixels.
63 */
64 GLboolean
65 intel_check_blit_fragment_ops(GLcontext * ctx, GLboolean src_alpha_is_one)
66 {
67 if (ctx->NewState)
68 _mesa_update_state(ctx);
69
70 if (ctx->FragmentProgram._Enabled) {
71 DBG("fallback due to fragment program\n");
72 return GL_FALSE;
73 }
74
75 if (ctx->Color.BlendEnabled &&
76 (effective_func(ctx->Color.BlendSrcRGB, src_alpha_is_one) != GL_ONE ||
77 effective_func(ctx->Color.BlendDstRGB, src_alpha_is_one) != GL_ZERO ||
78 ctx->Color.BlendEquationRGB != GL_FUNC_ADD ||
79 effective_func(ctx->Color.BlendSrcA, src_alpha_is_one) != GL_ONE ||
80 effective_func(ctx->Color.BlendDstA, src_alpha_is_one) != GL_ZERO ||
81 ctx->Color.BlendEquationA != GL_FUNC_ADD)) {
82 DBG("fallback due to blend\n");
83 return GL_FALSE;
84 }
85
86 if (ctx->Texture._EnabledUnits) {
87 DBG("fallback due to texturing\n");
88 return GL_FALSE;
89 }
90
91 if (!(ctx->Color.ColorMask[0] &&
92 ctx->Color.ColorMask[1] &&
93 ctx->Color.ColorMask[2] &&
94 ctx->Color.ColorMask[3])) {
95 DBG("fallback due to color masking\n");
96 return GL_FALSE;
97 }
98
99 if (ctx->Color.AlphaEnabled) {
100 DBG("fallback due to alpha\n");
101 return GL_FALSE;
102 }
103
104 if (ctx->Depth.Test) {
105 DBG("fallback due to depth test\n");
106 return GL_FALSE;
107 }
108
109 if (ctx->Fog.Enabled) {
110 DBG("fallback due to fog\n");
111 return GL_FALSE;
112 }
113
114 if (ctx->_ImageTransferState) {
115 DBG("fallback due to image transfer\n");
116 return GL_FALSE;
117 }
118
119 if (ctx->Stencil._Enabled) {
120 DBG("fallback due to image stencil\n");
121 return GL_FALSE;
122 }
123
124 if (ctx->RenderMode != GL_RENDER) {
125 DBG("fallback due to render mode\n");
126 return GL_FALSE;
127 }
128
129 return GL_TRUE;
130 }
131
132
133 GLboolean
134 intel_check_meta_tex_fragment_ops(GLcontext * ctx)
135 {
136 if (ctx->NewState)
137 _mesa_update_state(ctx);
138
139 /* Some of _ImageTransferState (scale, bias) could be done with
140 * fragment programs on i915.
141 */
142 return !(ctx->_ImageTransferState || ctx->Fog.Enabled || /* not done yet */
143 ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled);
144 }
145
146 /* The intel_region struct doesn't really do enough to capture the
147 * format of the pixels in the region. For now this code assumes that
148 * the region is a display surface and hence is either ARGB8888 or
149 * RGB565.
150 * XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd
151 * know the buffer's pixel format.
152 *
153 * \param format as given to glDraw/ReadPixels
154 * \param type as given to glDraw/ReadPixels
155 */
156 GLboolean
157 intel_check_blit_format(struct intel_region * region,
158 GLenum format, GLenum type)
159 {
160 if (region->cpp == 4 &&
161 (type == GL_UNSIGNED_INT_8_8_8_8_REV ||
162 type == GL_UNSIGNED_BYTE) && format == GL_BGRA) {
163 return GL_TRUE;
164 }
165
166 if (region->cpp == 2 &&
167 type == GL_UNSIGNED_SHORT_5_6_5_REV && format == GL_BGR) {
168 return GL_TRUE;
169 }
170
171 if (INTEL_DEBUG & DEBUG_PIXEL)
172 fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n",
173 __FUNCTION__, region->cpp,
174 _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
175
176 return GL_FALSE;
177 }
178
179 void
180 intel_meta_set_passthrough_transform(struct intel_context *intel)
181 {
182 GLcontext *ctx = &intel->ctx;
183
184 intel->meta.saved_vp_x = ctx->Viewport.X;
185 intel->meta.saved_vp_y = ctx->Viewport.Y;
186 intel->meta.saved_vp_width = ctx->Viewport.Width;
187 intel->meta.saved_vp_height = ctx->Viewport.Height;
188 intel->meta.saved_matrix_mode = ctx->Transform.MatrixMode;
189
190 intel->internal_viewport_call = GL_TRUE;
191 _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
192 intel->internal_viewport_call = GL_FALSE;
193
194 _mesa_MatrixMode(GL_PROJECTION);
195 _mesa_PushMatrix();
196 _mesa_LoadIdentity();
197 _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1);
198
199 _mesa_MatrixMode(GL_MODELVIEW);
200 _mesa_PushMatrix();
201 _mesa_LoadIdentity();
202 }
203
204 void
205 intel_meta_restore_transform(struct intel_context *intel)
206 {
207 _mesa_MatrixMode(GL_PROJECTION);
208 _mesa_PopMatrix();
209 _mesa_MatrixMode(GL_MODELVIEW);
210 _mesa_PopMatrix();
211
212 _mesa_MatrixMode(intel->meta.saved_matrix_mode);
213
214 intel->internal_viewport_call = GL_TRUE;
215 _mesa_Viewport(intel->meta.saved_vp_x, intel->meta.saved_vp_y,
216 intel->meta.saved_vp_width, intel->meta.saved_vp_height);
217 intel->internal_viewport_call = GL_FALSE;
218 }
219
220 /**
221 * Set up a vertex program to pass through the position and first texcoord
222 * for pixel path.
223 */
224 void
225 intel_meta_set_passthrough_vertex_program(struct intel_context *intel)
226 {
227 GLcontext *ctx = &intel->ctx;
228 static const char *vp =
229 "!!ARBvp1.0\n"
230 "TEMP vertexClip;\n"
231 "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
232 "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
233 "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
234 "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
235 "MOV result.position, vertexClip;\n"
236 "MOV result.texcoord[0], vertex.texcoord[0];\n"
237 "MOV result.color, vertex.color;\n"
238 "END\n";
239
240 assert(intel->meta.saved_vp == NULL);
241
242 _mesa_reference_vertprog(ctx, &intel->meta.saved_vp,
243 ctx->VertexProgram.Current);
244 if (intel->meta.passthrough_vp == NULL) {
245 GLuint prog_name;
246 _mesa_GenPrograms(1, &prog_name);
247 _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name);
248 _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB,
249 GL_PROGRAM_FORMAT_ASCII_ARB,
250 strlen(vp), (const GLubyte *)vp);
251 _mesa_reference_vertprog(ctx, &intel->meta.passthrough_vp,
252 ctx->VertexProgram.Current);
253 _mesa_DeletePrograms(1, &prog_name);
254 }
255
256 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
257 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
258 intel->meta.passthrough_vp);
259 ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
260 &intel->meta.passthrough_vp->Base);
261
262 intel->meta.saved_vp_enable = ctx->VertexProgram.Enabled;
263 _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
264 }
265
266 /**
267 * Restores the previous vertex program after
268 * intel_meta_set_passthrough_vertex_program()
269 */
270 void
271 intel_meta_restore_vertex_program(struct intel_context *intel)
272 {
273 GLcontext *ctx = &intel->ctx;
274
275 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
276 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
277 intel->meta.saved_vp);
278 _mesa_reference_vertprog(ctx, &intel->meta.saved_vp, NULL);
279 ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
280 &ctx->VertexProgram.Current->Base);
281
282 if (!intel->meta.saved_vp_enable)
283 _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
284 }
285
286 /**
287 * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the
288 * program object.
289 */
290 void
291 intel_meta_set_fragment_program(struct intel_context *intel,
292 struct gl_fragment_program **prog,
293 const char *prog_string)
294 {
295 GLcontext *ctx = &intel->ctx;
296 assert(intel->meta.saved_fp == NULL);
297
298 _mesa_reference_fragprog(ctx, &intel->meta.saved_fp,
299 ctx->FragmentProgram.Current);
300 if (*prog == NULL) {
301 GLuint prog_name;
302 _mesa_GenPrograms(1, &prog_name);
303 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name);
304 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
305 GL_PROGRAM_FORMAT_ASCII_ARB,
306 strlen(prog_string), (const GLubyte *)prog_string);
307 _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current);
308 /* Note that DeletePrograms unbinds the program on us */
309 _mesa_DeletePrograms(1, &prog_name);
310 }
311
312 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
313 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog);
314 ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base));
315
316 intel->meta.saved_fp_enable = ctx->FragmentProgram.Enabled;
317 _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
318 }
319
320 /**
321 * Restores the previous fragment program after
322 * intel_meta_set_fragment_program()
323 */
324 void
325 intel_meta_restore_fragment_program(struct intel_context *intel)
326 {
327 GLcontext *ctx = &intel->ctx;
328
329 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
330 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
331 intel->meta.saved_fp);
332 _mesa_reference_fragprog(ctx, &intel->meta.saved_fp, NULL);
333 ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
334 &ctx->FragmentProgram.Current->Base);
335
336 if (!intel->meta.saved_fp_enable)
337 _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
338 }
339
340 static const float default_texcoords[4][2] = { { 0.0, 0.0 },
341 { 1.0, 0.0 },
342 { 1.0, 1.0 },
343 { 0.0, 1.0 } };
344
345 void
346 intel_meta_set_default_texrect(struct intel_context *intel)
347 {
348 GLcontext *ctx = &intel->ctx;
349 struct gl_client_array *old_texcoord_array;
350
351 intel->meta.saved_active_texture = ctx->Texture.CurrentUnit;
352 if (intel->meta.saved_array_vbo == NULL) {
353 _mesa_reference_buffer_object(ctx, &intel->meta.saved_array_vbo,
354 ctx->Array.ArrayBufferObj);
355 }
356
357 old_texcoord_array = &ctx->Array.ArrayObj->TexCoord[0];
358 intel->meta.saved_texcoord_type = old_texcoord_array->Type;
359 intel->meta.saved_texcoord_size = old_texcoord_array->Size;
360 intel->meta.saved_texcoord_stride = old_texcoord_array->Stride;
361 intel->meta.saved_texcoord_enable = old_texcoord_array->Enabled;
362 intel->meta.saved_texcoord_ptr = old_texcoord_array->Ptr;
363 _mesa_reference_buffer_object(ctx, &intel->meta.saved_texcoord_vbo,
364 old_texcoord_array->BufferObj);
365
366 _mesa_ClientActiveTextureARB(GL_TEXTURE0);
367
368 if (intel->meta.texcoord_vbo == NULL) {
369 GLuint vbo_name;
370
371 _mesa_GenBuffersARB(1, &vbo_name);
372 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_name);
373 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(default_texcoords),
374 default_texcoords, GL_STATIC_DRAW_ARB);
375 _mesa_reference_buffer_object(ctx, &intel->meta.texcoord_vbo,
376 ctx->Array.ArrayBufferObj);
377 } else {
378 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
379 intel->meta.texcoord_vbo->Name);
380 }
381 _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), NULL);
382
383 _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
384 }
385
386 void
387 intel_meta_restore_texcoords(struct intel_context *intel)
388 {
389 GLcontext *ctx = &intel->ctx;
390
391 /* Restore the old TexCoordPointer */
392 if (intel->meta.saved_texcoord_vbo) {
393 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
394 intel->meta.saved_texcoord_vbo->Name);
395 _mesa_reference_buffer_object(ctx, &intel->meta.saved_texcoord_vbo, NULL);
396 } else {
397 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
398 }
399
400 _mesa_TexCoordPointer(intel->meta.saved_texcoord_size,
401 intel->meta.saved_texcoord_type,
402 intel->meta.saved_texcoord_stride,
403 intel->meta.saved_texcoord_ptr);
404 if (!intel->meta.saved_texcoord_enable)
405 _mesa_Disable(GL_TEXTURE_COORD_ARRAY);
406
407 _mesa_ClientActiveTextureARB(GL_TEXTURE0 +
408 intel->meta.saved_active_texture);
409
410 if (intel->meta.saved_array_vbo) {
411 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
412 intel->meta.saved_array_vbo->Name);
413 _mesa_reference_buffer_object(ctx, &intel->meta.saved_array_vbo, NULL);
414 } else {
415 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
416 }
417 }
418
419 void
420 intelInitPixelFuncs(struct dd_function_table *functions)
421 {
422 functions->Accum = _swrast_Accum;
423 if (!getenv("INTEL_NO_BLIT")) {
424 functions->Bitmap = intelBitmap;
425 functions->CopyPixels = intelCopyPixels;
426 functions->DrawPixels = intelDrawPixels;
427 #ifdef I915
428 functions->ReadPixels = intelReadPixels;
429 #endif
430 }
431 }
432
433 void
434 intel_free_pixel_state(struct intel_context *intel)
435 {
436 GLcontext *ctx = &intel->ctx;
437
438 _mesa_reference_vertprog(ctx, &intel->meta.passthrough_vp, NULL);
439 _mesa_reference_fragprog(ctx, &intel->meta.bitmap_fp, NULL);
440 _mesa_reference_fragprog(ctx, &intel->meta.tex2d_fp, NULL);
441 _mesa_reference_buffer_object(ctx, &intel->meta.texcoord_vbo, NULL);
442 }
443