i965: Add support for non-color render target write data to new FS backend.
[mesa.git] / src / mesa / drivers / dri / common / dri_metaops.c
1 /**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * Copyright 2009 Intel Corporation.
5 * 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
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * 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
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include "main/arbprogram.h"
30 #include "main/arrayobj.h"
31 #include "main/bufferobj.h"
32 #include "main/context.h"
33 #include "main/enable.h"
34 #include "main/matrix.h"
35 #include "main/texstate.h"
36 #include "main/varray.h"
37 #include "main/viewport.h"
38 #include "program/program.h"
39 #include "dri_metaops.h"
40
41 void
42 meta_set_passthrough_transform(struct dri_metaops *meta)
43 {
44 GLcontext *ctx = meta->ctx;
45
46 meta->saved_vp_x = ctx->Viewport.X;
47 meta->saved_vp_y = ctx->Viewport.Y;
48 meta->saved_vp_width = ctx->Viewport.Width;
49 meta->saved_vp_height = ctx->Viewport.Height;
50 meta->saved_matrix_mode = ctx->Transform.MatrixMode;
51
52 meta->internal_viewport_call = GL_TRUE;
53 _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
54 meta->internal_viewport_call = GL_FALSE;
55
56 _mesa_MatrixMode(GL_PROJECTION);
57 _mesa_PushMatrix();
58 _mesa_LoadIdentity();
59 _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1);
60
61 _mesa_MatrixMode(GL_MODELVIEW);
62 _mesa_PushMatrix();
63 _mesa_LoadIdentity();
64 }
65
66 void
67 meta_restore_transform(struct dri_metaops *meta)
68 {
69 _mesa_MatrixMode(GL_PROJECTION);
70 _mesa_PopMatrix();
71 _mesa_MatrixMode(GL_MODELVIEW);
72 _mesa_PopMatrix();
73
74 _mesa_MatrixMode(meta->saved_matrix_mode);
75
76 meta->internal_viewport_call = GL_TRUE;
77 _mesa_Viewport(meta->saved_vp_x, meta->saved_vp_y,
78 meta->saved_vp_width, meta->saved_vp_height);
79 meta->internal_viewport_call = GL_FALSE;
80 }
81
82
83 /**
84 * Set up a vertex program to pass through the position and first texcoord
85 * for pixel path.
86 */
87 void
88 meta_set_passthrough_vertex_program(struct dri_metaops *meta)
89 {
90 GLcontext *ctx = meta->ctx;
91 static const char *vp =
92 "!!ARBvp1.0\n"
93 "TEMP vertexClip;\n"
94 "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
95 "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
96 "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
97 "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
98 "MOV result.position, vertexClip;\n"
99 "MOV result.texcoord[0], vertex.texcoord[0];\n"
100 "MOV result.color, vertex.color;\n"
101 "END\n";
102
103 assert(meta->saved_vp == NULL);
104
105 _mesa_reference_vertprog(ctx, &meta->saved_vp,
106 ctx->VertexProgram.Current);
107 if (meta->passthrough_vp == NULL) {
108 GLuint prog_name;
109 _mesa_GenPrograms(1, &prog_name);
110 _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name);
111 _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB,
112 GL_PROGRAM_FORMAT_ASCII_ARB,
113 strlen(vp), (const GLubyte *)vp);
114 _mesa_reference_vertprog(ctx, &meta->passthrough_vp,
115 ctx->VertexProgram.Current);
116 _mesa_DeletePrograms(1, &prog_name);
117 }
118
119 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
120 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
121 meta->passthrough_vp);
122 ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
123 &meta->passthrough_vp->Base);
124
125 meta->saved_vp_enable = ctx->VertexProgram.Enabled;
126 _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
127 }
128
129 /**
130 * Restores the previous vertex program after
131 * meta_set_passthrough_vertex_program()
132 */
133 void
134 meta_restore_vertex_program(struct dri_metaops *meta)
135 {
136 GLcontext *ctx = meta->ctx;
137
138 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
139 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
140 meta->saved_vp);
141 _mesa_reference_vertprog(ctx, &meta->saved_vp, NULL);
142 ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
143 &ctx->VertexProgram.Current->Base);
144
145 if (!meta->saved_vp_enable)
146 _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
147 }
148
149 /**
150 * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the
151 * program object.
152 */
153 void
154 meta_set_fragment_program(struct dri_metaops *meta,
155 struct gl_fragment_program **prog,
156 const char *prog_string)
157 {
158 GLcontext *ctx = meta->ctx;
159 assert(meta->saved_fp == NULL);
160
161 _mesa_reference_fragprog(ctx, &meta->saved_fp,
162 ctx->FragmentProgram.Current);
163 if (*prog == NULL) {
164 GLuint prog_name;
165 _mesa_GenPrograms(1, &prog_name);
166 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name);
167 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
168 GL_PROGRAM_FORMAT_ASCII_ARB,
169 strlen(prog_string), (const GLubyte *)prog_string);
170 _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current);
171 /* Note that DeletePrograms unbinds the program on us */
172 _mesa_DeletePrograms(1, &prog_name);
173 }
174
175 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
176 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog);
177 ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base));
178
179 meta->saved_fp_enable = ctx->FragmentProgram.Enabled;
180 _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
181 }
182
183 /**
184 * Restores the previous fragment program after
185 * meta_set_fragment_program()
186 */
187 void
188 meta_restore_fragment_program(struct dri_metaops *meta)
189 {
190 GLcontext *ctx = meta->ctx;
191
192 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
193 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
194 meta->saved_fp);
195 _mesa_reference_fragprog(ctx, &meta->saved_fp, NULL);
196 ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
197 &ctx->FragmentProgram.Current->Base);
198
199 if (!meta->saved_fp_enable)
200 _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
201 }
202
203 static const float default_texcoords[4][2] = { { 0.0, 0.0 },
204 { 1.0, 0.0 },
205 { 1.0, 1.0 },
206 { 0.0, 1.0 } };
207
208 void
209 meta_set_default_texrect(struct dri_metaops *meta)
210 {
211 GLcontext *ctx = meta->ctx;
212 struct gl_client_array *old_texcoord_array;
213
214 meta->saved_active_texture = ctx->Texture.CurrentUnit;
215 if (meta->saved_array_vbo == NULL) {
216 _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo,
217 ctx->Array.ArrayBufferObj);
218 }
219
220 old_texcoord_array = &ctx->Array.ArrayObj->TexCoord[0];
221 meta->saved_texcoord_type = old_texcoord_array->Type;
222 meta->saved_texcoord_size = old_texcoord_array->Size;
223 meta->saved_texcoord_stride = old_texcoord_array->Stride;
224 meta->saved_texcoord_enable = old_texcoord_array->Enabled;
225 meta->saved_texcoord_ptr = old_texcoord_array->Ptr;
226 _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo,
227 old_texcoord_array->BufferObj);
228
229 _mesa_ClientActiveTextureARB(GL_TEXTURE0);
230
231 if (meta->texcoord_vbo == NULL) {
232 GLuint vbo_name;
233
234 _mesa_GenBuffersARB(1, &vbo_name);
235 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_name);
236 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(default_texcoords),
237 default_texcoords, GL_STATIC_DRAW_ARB);
238 _mesa_reference_buffer_object(ctx, &meta->texcoord_vbo,
239 ctx->Array.ArrayBufferObj);
240 } else {
241 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
242 meta->texcoord_vbo->Name);
243 }
244 _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), NULL);
245
246 _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
247 }
248
249 void
250 meta_restore_texcoords(struct dri_metaops *meta)
251 {
252 GLcontext *ctx = meta->ctx;
253
254 /* Restore the old TexCoordPointer */
255 if (meta->saved_texcoord_vbo) {
256 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
257 meta->saved_texcoord_vbo->Name);
258 _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, NULL);
259 } else {
260 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
261 }
262
263 _mesa_TexCoordPointer(meta->saved_texcoord_size,
264 meta->saved_texcoord_type,
265 meta->saved_texcoord_stride,
266 meta->saved_texcoord_ptr);
267 if (!meta->saved_texcoord_enable)
268 _mesa_Disable(GL_TEXTURE_COORD_ARRAY);
269
270 _mesa_ClientActiveTextureARB(GL_TEXTURE0 +
271 meta->saved_active_texture);
272
273 if (meta->saved_array_vbo) {
274 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
275 meta->saved_array_vbo->Name);
276 _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, NULL);
277 } else {
278 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
279 }
280 }
281
282
283 void meta_init_metaops(GLcontext *ctx, struct dri_metaops *meta)
284 {
285 meta->ctx = ctx;
286 }
287
288 void meta_destroy_metaops(struct dri_metaops *meta)
289 {
290
291 }