Merge remote branch 'origin/7.8'
[mesa.git] / src / mesa / drivers / dri / intel / intel_span.c
1 /**************************************************************************
2 *
3 * Copyright 2003 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 portions
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/glheader.h"
29 #include "main/macros.h"
30 #include "main/mtypes.h"
31 #include "main/colormac.h"
32
33 #include "intel_buffers.h"
34 #include "intel_fbo.h"
35 #include "intel_screen.h"
36 #include "intel_span.h"
37 #include "intel_regions.h"
38 #include "intel_tex.h"
39
40 #include "swrast/swrast.h"
41
42 static void
43 intel_set_span_functions(struct intel_context *intel,
44 struct gl_renderbuffer *rb);
45
46 #undef DBG
47 #define DBG 0
48
49 #define LOCAL_VARS \
50 struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
51 const GLint yScale = rb->Name ? 1 : -1; \
52 const GLint yBias = rb->Name ? 0 : rb->Height - 1; \
53 int minx = 0, miny = 0; \
54 int maxx = rb->Width; \
55 int maxy = rb->Height; \
56 int pitch = irb->region->pitch * irb->region->cpp; \
57 void *buf = irb->region->buffer->virtual; \
58 GLuint p; \
59 (void) p; \
60 (void)buf; (void)pitch; /* unused for non-gttmap. */ \
61
62 #define HW_CLIPLOOP()
63 #define HW_ENDCLIPLOOP()
64
65 #define Y_FLIP(_y) ((_y) * yScale + yBias)
66
67 #define HW_LOCK()
68
69 #define HW_UNLOCK()
70
71 /* Convenience macros to avoid typing the address argument over and over */
72 #define NO_TILE(_X, _Y) (((_Y) * irb->region->pitch + (_X)) * irb->region->cpp)
73
74 /* r5g6b5 color span and pixel functions */
75 #define SPANTMP_PIXEL_FMT GL_RGB
76 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
77 #define TAG(x) intel_##x##_RGB565
78 #define TAG2(x,y) intel_##x##y_RGB565
79 #include "spantmp2.h"
80
81 /* a4r4g4b4 color span and pixel functions */
82 #define SPANTMP_PIXEL_FMT GL_BGRA
83 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_4_4_4_4_REV
84 #define TAG(x) intel_##x##_ARGB4444
85 #define TAG2(x,y) intel_##x##y_ARGB4444
86 #include "spantmp2.h"
87
88 /* a1r5g5b5 color span and pixel functions */
89 #define SPANTMP_PIXEL_FMT GL_BGRA
90 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_1_5_5_5_REV
91 #define TAG(x) intel_##x##_ARGB1555
92 #define TAG2(x,y) intel_##x##y##_ARGB1555
93 #include "spantmp2.h"
94
95 /* a8r8g8b8 color span and pixel functions */
96 #define SPANTMP_PIXEL_FMT GL_BGRA
97 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
98 #define TAG(x) intel_##x##_ARGB8888
99 #define TAG2(x,y) intel_##x##y##_ARGB8888
100 #include "spantmp2.h"
101
102 /* x8r8g8b8 color span and pixel functions */
103 #define SPANTMP_PIXEL_FMT GL_BGR
104 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
105 #define TAG(x) intel_##x##_xRGB8888
106 #define TAG2(x,y) intel_##x##y##_xRGB8888
107 #include "spantmp2.h"
108
109 #define LOCAL_DEPTH_VARS \
110 struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
111 const GLint yScale = rb->Name ? 1 : -1; \
112 const GLint yBias = rb->Name ? 0 : rb->Height - 1; \
113 int minx = 0, miny = 0; \
114 int maxx = rb->Width; \
115 int maxy = rb->Height; \
116 int pitch = irb->region->pitch * irb->region->cpp; \
117 void *buf = irb->region->buffer->virtual; \
118 (void)buf; (void)pitch; /* unused for non-gttmap. */ \
119
120 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
121
122 /* z16 depthbuffer functions. */
123 #define VALUE_TYPE GLushort
124 #define WRITE_DEPTH(_x, _y, d) \
125 (*(uint16_t *)(irb->region->buffer->virtual + NO_TILE(_x, _y)) = d)
126 #define READ_DEPTH(d, _x, _y) \
127 d = *(uint16_t *)(irb->region->buffer->virtual + NO_TILE(_x, _y))
128 #define TAG(x) intel_##x##_z16
129 #include "depthtmp.h"
130
131 /* z24_s8 and z24_x8 depthbuffer functions. */
132 #define VALUE_TYPE GLuint
133 #define WRITE_DEPTH(_x, _y, d) \
134 (*(uint32_t *)(irb->region->buffer->virtual + NO_TILE(_x, _y)) = d)
135 #define READ_DEPTH(d, _x, _y) \
136 d = *(uint32_t *)(irb->region->buffer->virtual + NO_TILE(_x, _y))
137 #define TAG(x) intel_##x##_z24_s8
138 #include "depthtmp.h"
139
140 void
141 intel_renderbuffer_map(struct intel_context *intel, struct gl_renderbuffer *rb)
142 {
143 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
144
145 if (irb == NULL || irb->region == NULL)
146 return;
147
148 drm_intel_gem_bo_map_gtt(irb->region->buffer);
149
150 intel_set_span_functions(intel, rb);
151 }
152
153 void
154 intel_renderbuffer_unmap(struct intel_context *intel,
155 struct gl_renderbuffer *rb)
156 {
157 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
158
159 if (irb == NULL || irb->region == NULL)
160 return;
161
162 drm_intel_gem_bo_unmap_gtt(irb->region->buffer);
163
164 rb->GetRow = NULL;
165 rb->PutRow = NULL;
166 }
167
168 /**
169 * Map or unmap all the renderbuffers which we may need during
170 * software rendering.
171 * XXX in the future, we could probably convey extra information to
172 * reduce the number of mappings needed. I.e. if doing a glReadPixels
173 * from the depth buffer, we really only need one mapping.
174 *
175 * XXX Rewrite this function someday.
176 * We can probably just loop over all the renderbuffer attachments,
177 * map/unmap all of them, and not worry about the _ColorDrawBuffers
178 * _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields.
179 */
180 static void
181 intel_map_unmap_framebuffer(struct intel_context *intel,
182 struct gl_framebuffer *fb,
183 GLboolean map)
184 {
185 GLuint i;
186
187 /* color draw buffers */
188 for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
189 if (map)
190 intel_renderbuffer_map(intel, fb->_ColorDrawBuffers[i]);
191 else
192 intel_renderbuffer_unmap(intel, fb->_ColorDrawBuffers[i]);
193 }
194
195 /* color read buffer */
196 if (map)
197 intel_renderbuffer_map(intel, fb->_ColorReadBuffer);
198 else
199 intel_renderbuffer_unmap(intel, fb->_ColorReadBuffer);
200
201 /* check for render to textures */
202 for (i = 0; i < BUFFER_COUNT; i++) {
203 struct gl_renderbuffer_attachment *att =
204 fb->Attachment + i;
205 struct gl_texture_object *tex = att->Texture;
206 if (tex) {
207 /* render to texture */
208 ASSERT(att->Renderbuffer);
209 if (map)
210 intel_tex_map_images(intel, intel_texture_object(tex));
211 else
212 intel_tex_unmap_images(intel, intel_texture_object(tex));
213 }
214 }
215
216 /* depth buffer (Note wrapper!) */
217 if (fb->_DepthBuffer) {
218 if (map)
219 intel_renderbuffer_map(intel, fb->_DepthBuffer->Wrapped);
220 else
221 intel_renderbuffer_unmap(intel, fb->_DepthBuffer->Wrapped);
222 }
223
224 /* stencil buffer (Note wrapper!) */
225 if (fb->_StencilBuffer) {
226 if (map)
227 intel_renderbuffer_map(intel, fb->_StencilBuffer->Wrapped);
228 else
229 intel_renderbuffer_unmap(intel, fb->_StencilBuffer->Wrapped);
230 }
231
232 intel_check_front_buffer_rendering(intel);
233 }
234
235 /**
236 * Prepare for software rendering. Map current read/draw framebuffers'
237 * renderbuffes and all currently bound texture objects.
238 *
239 * Old note: Moved locking out to get reasonable span performance.
240 */
241 void
242 intelSpanRenderStart(GLcontext * ctx)
243 {
244 struct intel_context *intel = intel_context(ctx);
245 GLuint i;
246
247 intelFlush(&intel->ctx);
248 intel_prepare_render(intel);
249
250 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
251 if (ctx->Texture.Unit[i]._ReallyEnabled) {
252 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
253 intel_tex_map_images(intel, intel_texture_object(texObj));
254 }
255 }
256
257 intel_map_unmap_framebuffer(intel, ctx->DrawBuffer, GL_TRUE);
258 if (ctx->ReadBuffer != ctx->DrawBuffer)
259 intel_map_unmap_framebuffer(intel, ctx->ReadBuffer, GL_TRUE);
260 }
261
262 /**
263 * Called when done software rendering. Unmap the buffers we mapped in
264 * the above function.
265 */
266 void
267 intelSpanRenderFinish(GLcontext * ctx)
268 {
269 struct intel_context *intel = intel_context(ctx);
270 GLuint i;
271
272 _swrast_flush(ctx);
273
274 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
275 if (ctx->Texture.Unit[i]._ReallyEnabled) {
276 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
277 intel_tex_unmap_images(intel, intel_texture_object(texObj));
278 }
279 }
280
281 intel_map_unmap_framebuffer(intel, ctx->DrawBuffer, GL_FALSE);
282 if (ctx->ReadBuffer != ctx->DrawBuffer)
283 intel_map_unmap_framebuffer(intel, ctx->ReadBuffer, GL_FALSE);
284 }
285
286
287 void
288 intelInitSpanFuncs(GLcontext * ctx)
289 {
290 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
291 swdd->SpanRenderStart = intelSpanRenderStart;
292 swdd->SpanRenderFinish = intelSpanRenderFinish;
293 }
294
295 void
296 intel_map_vertex_shader_textures(GLcontext *ctx)
297 {
298 struct intel_context *intel = intel_context(ctx);
299 int i;
300
301 if (ctx->VertexProgram._Current == NULL)
302 return;
303
304 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
305 if (ctx->Texture.Unit[i]._ReallyEnabled &&
306 ctx->VertexProgram._Current->Base.TexturesUsed[i] != 0) {
307 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
308
309 intel_tex_map_images(intel, intel_texture_object(texObj));
310 }
311 }
312 }
313
314 void
315 intel_unmap_vertex_shader_textures(GLcontext *ctx)
316 {
317 struct intel_context *intel = intel_context(ctx);
318 int i;
319
320 if (ctx->VertexProgram._Current == NULL)
321 return;
322
323 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
324 if (ctx->Texture.Unit[i]._ReallyEnabled &&
325 ctx->VertexProgram._Current->Base.TexturesUsed[i] != 0) {
326 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
327
328 intel_tex_unmap_images(intel, intel_texture_object(texObj));
329 }
330 }
331 }
332
333 /**
334 * Plug in appropriate span read/write functions for the given renderbuffer.
335 * These are used for the software fallbacks.
336 */
337 static void
338 intel_set_span_functions(struct intel_context *intel,
339 struct gl_renderbuffer *rb)
340 {
341 struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
342
343 switch (irb->Base.Format) {
344 case MESA_FORMAT_RGB565:
345 intel_InitPointers_RGB565(rb);
346 break;
347 case MESA_FORMAT_ARGB4444:
348 intel_InitPointers_ARGB4444(rb);
349 break;
350 case MESA_FORMAT_ARGB1555:
351 intel_InitPointers_ARGB1555(rb);
352 break;
353 case MESA_FORMAT_XRGB8888:
354 intel_InitPointers_xRGB8888(rb);
355 break;
356 case MESA_FORMAT_ARGB8888:
357 intel_InitPointers_ARGB8888(rb);
358 break;
359 case MESA_FORMAT_Z16:
360 intel_InitDepthPointers_z16(rb);
361 break;
362 case MESA_FORMAT_X8_Z24:
363 case MESA_FORMAT_S8_Z24:
364 intel_InitDepthPointers_z24_s8(rb);
365 break;
366 default:
367 _mesa_problem(NULL,
368 "Unexpected MesaFormat %d in intelSetSpanFunctions",
369 irb->Base.Format);
370 break;
371 }
372 }