radeon/r200/r300: cleanup some of the renderbuffer code
[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/context.h"
31 #include "main/enable.h"
32 #include "main/matrix.h"
33 #include "swrast/swrast.h"
34 #include "shader/arbprogram.h"
35 #include "shader/program.h"
36
37 #include "intel_context.h"
38 #include "intel_pixel.h"
39 #include "intel_regions.h"
40
41 #define FILE_DEBUG_FLAG DEBUG_PIXEL
42
43 static GLenum
44 effective_func(GLenum func, GLboolean src_alpha_is_one)
45 {
46 if (src_alpha_is_one) {
47 if (func == GL_SRC_ALPHA)
48 return GL_ONE;
49 if (func == GL_ONE_MINUS_SRC_ALPHA)
50 return GL_ZERO;
51 }
52
53 return func;
54 }
55
56 /**
57 * Check if any fragment operations are in effect which might effect
58 * glDraw/CopyPixels.
59 */
60 GLboolean
61 intel_check_blit_fragment_ops(GLcontext * ctx, GLboolean src_alpha_is_one)
62 {
63 if (ctx->NewState)
64 _mesa_update_state(ctx);
65
66 if (ctx->FragmentProgram._Enabled) {
67 DBG("fallback due to fragment program\n");
68 return GL_FALSE;
69 }
70
71 if (ctx->Color.BlendEnabled &&
72 (effective_func(ctx->Color.BlendSrcRGB, src_alpha_is_one) != GL_ONE ||
73 effective_func(ctx->Color.BlendDstRGB, src_alpha_is_one) != GL_ZERO ||
74 ctx->Color.BlendEquationRGB != GL_FUNC_ADD ||
75 effective_func(ctx->Color.BlendSrcA, src_alpha_is_one) != GL_ONE ||
76 effective_func(ctx->Color.BlendDstA, src_alpha_is_one) != GL_ZERO ||
77 ctx->Color.BlendEquationA != GL_FUNC_ADD)) {
78 DBG("fallback due to blend\n");
79 return GL_FALSE;
80 }
81
82 if (ctx->Texture._EnabledUnits) {
83 DBG("fallback due to texturing\n");
84 return GL_FALSE;
85 }
86
87 if (!(ctx->Color.ColorMask[0] &&
88 ctx->Color.ColorMask[1] &&
89 ctx->Color.ColorMask[2] &&
90 ctx->Color.ColorMask[3])) {
91 DBG("fallback due to color masking\n");
92 return GL_FALSE;
93 }
94
95 if (ctx->Color.AlphaEnabled) {
96 DBG("fallback due to alpha\n");
97 return GL_FALSE;
98 }
99
100 if (ctx->Depth.Test) {
101 DBG("fallback due to depth test\n");
102 return GL_FALSE;
103 }
104
105 if (ctx->Fog.Enabled) {
106 DBG("fallback due to fog\n");
107 return GL_FALSE;
108 }
109
110 if (ctx->_ImageTransferState) {
111 DBG("fallback due to image transfer\n");
112 return GL_FALSE;
113 }
114
115 if (ctx->Stencil.Enabled) {
116 DBG("fallback due to image stencil\n");
117 return GL_FALSE;
118 }
119
120 if (ctx->RenderMode != GL_RENDER) {
121 DBG("fallback due to render mode\n");
122 return GL_FALSE;
123 }
124
125 return GL_TRUE;
126 }
127
128
129 GLboolean
130 intel_check_meta_tex_fragment_ops(GLcontext * ctx)
131 {
132 if (ctx->NewState)
133 _mesa_update_state(ctx);
134
135 /* Some of _ImageTransferState (scale, bias) could be done with
136 * fragment programs on i915.
137 */
138 return !(ctx->_ImageTransferState || ctx->Fog.Enabled || /* not done yet */
139 ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled);
140 }
141
142 /* The intel_region struct doesn't really do enough to capture the
143 * format of the pixels in the region. For now this code assumes that
144 * the region is a display surface and hence is either ARGB8888 or
145 * RGB565.
146 * XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd
147 * know the buffer's pixel format.
148 *
149 * \param format as given to glDraw/ReadPixels
150 * \param type as given to glDraw/ReadPixels
151 */
152 GLboolean
153 intel_check_blit_format(struct intel_region * region,
154 GLenum format, GLenum type)
155 {
156 if (region->cpp == 4 &&
157 (type == GL_UNSIGNED_INT_8_8_8_8_REV ||
158 type == GL_UNSIGNED_BYTE) && format == GL_BGRA) {
159 return GL_TRUE;
160 }
161
162 if (region->cpp == 2 &&
163 type == GL_UNSIGNED_SHORT_5_6_5_REV && format == GL_BGR) {
164 return GL_TRUE;
165 }
166
167 if (INTEL_DEBUG & DEBUG_PIXEL)
168 fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n",
169 __FUNCTION__, region->cpp,
170 _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
171
172 return GL_FALSE;
173 }
174
175 void
176 intel_meta_set_passthrough_transform(struct intel_context *intel)
177 {
178 GLcontext *ctx = &intel->ctx;
179
180 intel->meta.saved_vp_x = ctx->Viewport.X;
181 intel->meta.saved_vp_y = ctx->Viewport.Y;
182 intel->meta.saved_vp_width = ctx->Viewport.Width;
183 intel->meta.saved_vp_height = ctx->Viewport.Height;
184 intel->meta.saved_matrix_mode = ctx->Transform.MatrixMode;
185
186 _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
187
188 _mesa_MatrixMode(GL_PROJECTION);
189 _mesa_PushMatrix();
190 _mesa_LoadIdentity();
191 _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1);
192
193 _mesa_MatrixMode(GL_MODELVIEW);
194 _mesa_PushMatrix();
195 _mesa_LoadIdentity();
196 }
197
198 void
199 intel_meta_restore_transform(struct intel_context *intel)
200 {
201 _mesa_MatrixMode(GL_PROJECTION);
202 _mesa_PopMatrix();
203 _mesa_MatrixMode(GL_MODELVIEW);
204 _mesa_PopMatrix();
205
206 _mesa_MatrixMode(intel->meta.saved_matrix_mode);
207
208 _mesa_Viewport(intel->meta.saved_vp_x, intel->meta.saved_vp_y,
209 intel->meta.saved_vp_width, intel->meta.saved_vp_height);
210 }
211
212 /**
213 * Set up a vertex program to pass through the position and first texcoord
214 * for pixel path.
215 */
216 void
217 intel_meta_set_passthrough_vertex_program(struct intel_context *intel)
218 {
219 GLcontext *ctx = &intel->ctx;
220 static const char *vp =
221 "!!ARBvp1.0\n"
222 "TEMP vertexClip;\n"
223 "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
224 "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
225 "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
226 "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
227 "MOV result.position, vertexClip;\n"
228 "MOV result.texcoord[0], vertex.texcoord[0];\n"
229 "MOV result.color, vertex.color;\n"
230 "END\n";
231
232 assert(intel->meta.saved_vp == NULL);
233
234 _mesa_reference_vertprog(ctx, &intel->meta.saved_vp,
235 ctx->VertexProgram.Current);
236 if (intel->meta.passthrough_vp == NULL) {
237 GLuint prog_name;
238 _mesa_GenPrograms(1, &prog_name);
239 _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name);
240 _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB,
241 GL_PROGRAM_FORMAT_ASCII_ARB,
242 strlen(vp), (const GLubyte *)vp);
243 _mesa_reference_vertprog(ctx, &intel->meta.passthrough_vp,
244 ctx->VertexProgram.Current);
245 _mesa_DeletePrograms(1, &prog_name);
246 }
247
248 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
249 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
250 intel->meta.passthrough_vp);
251 ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
252 &intel->meta.passthrough_vp->Base);
253
254 intel->meta.saved_vp_enable = ctx->VertexProgram.Enabled;
255 _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
256 }
257
258 /**
259 * Restores the previous vertex program after
260 * intel_meta_set_passthrough_vertex_program()
261 */
262 void
263 intel_meta_restore_vertex_program(struct intel_context *intel)
264 {
265 GLcontext *ctx = &intel->ctx;
266
267 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
268 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
269 intel->meta.saved_vp);
270 _mesa_reference_vertprog(ctx, &intel->meta.saved_vp, NULL);
271 ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
272 &ctx->VertexProgram.Current->Base);
273
274 if (!intel->meta.saved_vp_enable)
275 _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
276 }
277
278 /**
279 * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the
280 * program object.
281 */
282 void
283 intel_meta_set_fragment_program(struct intel_context *intel,
284 struct gl_fragment_program **prog,
285 const char *prog_string)
286 {
287 GLcontext *ctx = &intel->ctx;
288 assert(intel->meta.saved_fp == NULL);
289
290 _mesa_reference_fragprog(ctx, &intel->meta.saved_fp,
291 ctx->FragmentProgram.Current);
292 if (*prog == NULL) {
293 GLuint prog_name;
294 _mesa_GenPrograms(1, &prog_name);
295 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name);
296 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
297 GL_PROGRAM_FORMAT_ASCII_ARB,
298 strlen(prog_string), (const GLubyte *)prog_string);
299 _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current);
300 /* Note that DeletePrograms unbinds the program on us */
301 _mesa_DeletePrograms(1, &prog_name);
302 }
303
304 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
305 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog);
306 ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base));
307
308 intel->meta.saved_fp_enable = ctx->FragmentProgram.Enabled;
309 _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
310 }
311
312 /**
313 * Restores the previous fragment program after
314 * intel_meta_set_fragment_program()
315 */
316 void
317 intel_meta_restore_fragment_program(struct intel_context *intel)
318 {
319 GLcontext *ctx = &intel->ctx;
320
321 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
322 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
323 intel->meta.saved_fp);
324 _mesa_reference_fragprog(ctx, &intel->meta.saved_fp, NULL);
325 ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
326 &ctx->FragmentProgram.Current->Base);
327
328 if (!intel->meta.saved_fp_enable)
329 _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
330 }
331
332 void
333 intelInitPixelFuncs(struct dd_function_table *functions)
334 {
335 functions->Accum = _swrast_Accum;
336 if (!getenv("INTEL_NO_BLIT")) {
337 functions->Bitmap = intelBitmap;
338 functions->CopyPixels = intelCopyPixels;
339 functions->DrawPixels = intelDrawPixels;
340 #ifdef I915
341 functions->ReadPixels = intelReadPixels;
342 #endif
343 }
344 }
345
346 void
347 intel_free_pixel_state(struct intel_context *intel)
348 {
349 GLcontext *ctx = &intel->ctx;
350
351 _mesa_reference_vertprog(ctx, &intel->meta.passthrough_vp, NULL);
352 _mesa_reference_fragprog(ctx, &intel->meta.bitmap_fp, NULL);
353 }
354