mesa: add/update comments in _mesa_copy_buffer_subdata()
[mesa.git] / src / mesa / drivers / dri / intel / intel_span.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * Copyright 2011 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 * Authors:
28 * Chad Versace <chad@chad-versace.us>
29 *
30 **************************************************************************/
31
32 #include <stdbool.h>
33 #include <stdint.h>
34 #include "main/glheader.h"
35 #include "main/macros.h"
36 #include "main/mtypes.h"
37 #include "main/colormac.h"
38 #include "main/renderbuffer.h"
39
40 #include "intel_buffers.h"
41 #include "intel_fbo.h"
42 #include "intel_mipmap_tree.h"
43 #include "intel_screen.h"
44 #include "intel_span.h"
45 #include "intel_regions.h"
46 #include "intel_tex.h"
47
48 #include "swrast/swrast.h"
49 #include "swrast/s_renderbuffer.h"
50
51 static void
52 intel_set_span_functions(struct intel_context *intel,
53 struct gl_renderbuffer *rb);
54
55 #undef DBG
56 #define DBG 0
57
58 #define LOCAL_VARS \
59 struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
60 int minx = 0, miny = 0; \
61 int maxx = rb->Width; \
62 int maxy = rb->Height; \
63 int pitch = rb->RowStride * irb->mt->region->cpp; \
64 void *buf = rb->Data; \
65 GLuint p; \
66 (void) p;
67
68 #define HW_CLIPLOOP()
69 #define HW_ENDCLIPLOOP()
70
71 #define Y_FLIP(_y) (_y)
72
73 #define HW_LOCK()
74
75 #define HW_UNLOCK()
76
77 /* r5g6b5 color span and pixel functions */
78 #define SPANTMP_PIXEL_FMT GL_RGB
79 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
80 #define TAG(x) intel_##x##_RGB565
81 #define TAG2(x,y) intel_##x##y_RGB565
82 #include "spantmp2.h"
83
84 /* a4r4g4b4 color span and pixel functions */
85 #define SPANTMP_PIXEL_FMT GL_BGRA
86 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_4_4_4_4_REV
87 #define TAG(x) intel_##x##_ARGB4444
88 #define TAG2(x,y) intel_##x##y_ARGB4444
89 #include "spantmp2.h"
90
91 /* a1r5g5b5 color span and pixel functions */
92 #define SPANTMP_PIXEL_FMT GL_BGRA
93 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_1_5_5_5_REV
94 #define TAG(x) intel_##x##_ARGB1555
95 #define TAG2(x,y) intel_##x##y##_ARGB1555
96 #include "spantmp2.h"
97
98 /* a8r8g8b8 color span and pixel functions */
99 #define SPANTMP_PIXEL_FMT GL_BGRA
100 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
101 #define TAG(x) intel_##x##_ARGB8888
102 #define TAG2(x,y) intel_##x##y##_ARGB8888
103 #include "spantmp2.h"
104
105 /* x8r8g8b8 color span and pixel functions */
106 #define SPANTMP_PIXEL_FMT GL_BGR
107 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
108 #define TAG(x) intel_##x##_xRGB8888
109 #define TAG2(x,y) intel_##x##y##_xRGB8888
110 #include "spantmp2.h"
111
112 /* a8 color span and pixel functions */
113 #define SPANTMP_PIXEL_FMT GL_ALPHA
114 #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_BYTE
115 #define TAG(x) intel_##x##_A8
116 #define TAG2(x,y) intel_##x##y##_A8
117 #include "spantmp2.h"
118
119 /**
120 * \brief Get pointer offset into stencil buffer.
121 *
122 * The stencil buffer is W tiled. Since the GTT is incapable of W fencing, we
123 * must decode the tile's layout in software.
124 *
125 * See
126 * - PRM, 2011 Sandy Bridge, Volume 1, Part 2, Section 4.5.2.1 W-Major Tile
127 * Format.
128 * - PRM, 2011 Sandy Bridge, Volume 1, Part 2, Section 4.5.3 Tiling Algorithm
129 *
130 * Even though the returned offset is always positive, the return type is
131 * signed due to
132 * commit e8b1c6d6f55f5be3bef25084fdd8b6127517e137
133 * mesa: Fix return type of _mesa_get_format_bytes() (#37351)
134 */
135 intptr_t
136 intel_offset_S8(uint32_t stride, uint32_t x, uint32_t y)
137 {
138 uint32_t tile_size = 4096;
139 uint32_t tile_width = 64;
140 uint32_t tile_height = 64;
141 uint32_t row_size = 64 * stride;
142
143 uint32_t tile_x = x / tile_width;
144 uint32_t tile_y = y / tile_height;
145
146 /* The byte's address relative to the tile's base addres. */
147 uint32_t byte_x = x % tile_width;
148 uint32_t byte_y = y % tile_height;
149
150 uintptr_t u = tile_y * row_size
151 + tile_x * tile_size
152 + 512 * (byte_x / 8)
153 + 64 * (byte_y / 8)
154 + 32 * ((byte_y / 4) % 2)
155 + 16 * ((byte_x / 4) % 2)
156 + 8 * ((byte_y / 2) % 2)
157 + 4 * ((byte_x / 2) % 2)
158 + 2 * (byte_y % 2)
159 + 1 * (byte_x % 2);
160
161 /*
162 * Errata for Gen5:
163 *
164 * An additional offset is needed which is not documented in the PRM.
165 *
166 * if ((byte_x / 8) % 2 == 1) {
167 * if ((byte_y / 8) % 2) == 0) {
168 * u += 64;
169 * } else {
170 * u -= 64;
171 * }
172 * }
173 *
174 * The offset is expressed more tersely as
175 * u += ((int) x & 0x8) * (8 - (((int) y & 0x8) << 1));
176 */
177
178 return u;
179 }
180
181 void
182 intel_renderbuffer_map(struct intel_context *intel, struct gl_renderbuffer *rb)
183 {
184 struct gl_context *ctx = &intel->ctx;
185 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
186 GLubyte *map;
187 int stride;
188
189 if (!irb)
190 return;
191
192 if (rb->Data) {
193 /* Renderbuffer is already mapped. This usually happens when a single
194 * buffer is attached to the framebuffer's depth and stencil attachment
195 * points.
196 */
197 return;
198 }
199
200 ctx->Driver.MapRenderbuffer(ctx, rb, 0, 0, rb->Width, rb->Height,
201 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
202 &map, &stride);
203 rb->Data = map;
204 rb->RowStride = stride / _mesa_get_format_bytes(rb->Format);
205
206 intel_set_span_functions(intel, rb);
207 }
208
209 void
210 intel_renderbuffer_unmap(struct intel_context *intel,
211 struct gl_renderbuffer *rb)
212 {
213 struct gl_context *ctx = &intel->ctx;
214 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
215
216 if (!irb)
217 return;
218
219 if (!rb->Data) {
220 /* Renderbuffer is already unmapped. This usually happens when a single
221 * buffer is attached to the framebuffer's depth and stencil attachment
222 * points.
223 */
224 return;
225 }
226
227 ctx->Driver.UnmapRenderbuffer(ctx, rb);
228
229 rb->GetRow = NULL;
230 rb->PutRow = NULL;
231 rb->Data = NULL;
232 rb->RowStride = 0;
233 }
234
235 static void
236 intel_framebuffer_map(struct intel_context *intel, struct gl_framebuffer *fb)
237 {
238 int i;
239
240 for (i = 0; i < BUFFER_COUNT; i++) {
241 intel_renderbuffer_map(intel, fb->Attachment[i].Renderbuffer);
242 }
243
244 intel_check_front_buffer_rendering(intel);
245 }
246
247 static void
248 intel_framebuffer_unmap(struct intel_context *intel, struct gl_framebuffer *fb)
249 {
250 int i;
251
252 for (i = 0; i < BUFFER_COUNT; i++) {
253 intel_renderbuffer_unmap(intel, fb->Attachment[i].Renderbuffer);
254 }
255 }
256
257 /**
258 * Resolve all buffers that will be mapped by intelSpanRenderStart().
259 *
260 * Resolve the depth buffer of each enabled texture and of the read and draw
261 * buffers.
262 *
263 * (Note: In the future this will also perform MSAA resolves.)
264 */
265 static void
266 intel_span_resolve_buffers(struct intel_context *intel)
267 {
268 struct gl_context *ctx = &intel->ctx;
269 struct intel_renderbuffer *draw_irb;
270 struct intel_renderbuffer *read_irb;
271 struct intel_texture_object *tex_obj;
272
273 /* Resolve depth buffer of each enabled texture. */
274 for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
275 if (!ctx->Texture.Unit[i]._ReallyEnabled)
276 continue;
277 tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
278 intel_finalize_mipmap_tree(intel, i);
279 if (!tex_obj || !tex_obj->mt)
280 continue;
281 intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt);
282 }
283
284 /* Resolve each attached depth buffer. */
285 draw_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH);
286 read_irb = intel_get_renderbuffer(ctx->ReadBuffer, BUFFER_DEPTH);
287 if (draw_irb)
288 intel_renderbuffer_resolve_depth(intel, draw_irb);
289 if (read_irb != draw_irb && read_irb)
290 intel_renderbuffer_resolve_depth(intel, read_irb);
291 }
292
293 /**
294 * Map the regions needed by intelSpanRenderStart().
295 */
296 static void
297 intel_span_map_buffers(struct intel_context *intel)
298 {
299 struct gl_context *ctx = &intel->ctx;
300 struct intel_texture_object *tex_obj;
301
302 for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
303 if (!ctx->Texture.Unit[i]._ReallyEnabled)
304 continue;
305 tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
306 intel_finalize_mipmap_tree(intel, i);
307 intel_tex_map_images(intel, tex_obj,
308 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
309 }
310
311 intel_framebuffer_map(intel, ctx->DrawBuffer);
312 if (ctx->ReadBuffer != ctx->DrawBuffer) {
313 intel_framebuffer_map(intel, ctx->ReadBuffer);
314 }
315 }
316
317 /**
318 * Prepare for software rendering. Map current read/draw framebuffers'
319 * renderbuffes and all currently bound texture objects.
320 *
321 * Old note: Moved locking out to get reasonable span performance.
322 */
323 void
324 intelSpanRenderStart(struct gl_context * ctx)
325 {
326 struct intel_context *intel = intel_context(ctx);
327
328 intel_flush(ctx);
329 intel_prepare_render(intel);
330 intel_span_resolve_buffers(intel);
331 intel_flush(ctx);
332 intel_span_map_buffers(intel);
333 }
334
335 /**
336 * Called when done software rendering. Unmap the buffers we mapped in
337 * the above function.
338 */
339 void
340 intelSpanRenderFinish(struct gl_context * ctx)
341 {
342 struct intel_context *intel = intel_context(ctx);
343 GLuint i;
344
345 _swrast_flush(ctx);
346
347 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
348 if (ctx->Texture.Unit[i]._ReallyEnabled) {
349 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
350 intel_tex_unmap_images(intel, intel_texture_object(texObj));
351 }
352 }
353
354 intel_framebuffer_unmap(intel, ctx->DrawBuffer);
355 if (ctx->ReadBuffer != ctx->DrawBuffer) {
356 intel_framebuffer_unmap(intel, ctx->ReadBuffer);
357 }
358 }
359
360
361 void
362 intelInitSpanFuncs(struct gl_context * ctx)
363 {
364 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
365 swdd->SpanRenderStart = intelSpanRenderStart;
366 swdd->SpanRenderFinish = intelSpanRenderFinish;
367 }
368
369 void
370 intel_map_vertex_shader_textures(struct gl_context *ctx)
371 {
372 struct intel_context *intel = intel_context(ctx);
373 int i;
374
375 if (ctx->VertexProgram._Current == NULL)
376 return;
377
378 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
379 if (ctx->Texture.Unit[i]._ReallyEnabled &&
380 ctx->VertexProgram._Current->Base.TexturesUsed[i] != 0) {
381 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
382
383 intel_tex_map_images(intel, intel_texture_object(texObj),
384 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
385 }
386 }
387 }
388
389 void
390 intel_unmap_vertex_shader_textures(struct gl_context *ctx)
391 {
392 struct intel_context *intel = intel_context(ctx);
393 int i;
394
395 if (ctx->VertexProgram._Current == NULL)
396 return;
397
398 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
399 if (ctx->Texture.Unit[i]._ReallyEnabled &&
400 ctx->VertexProgram._Current->Base.TexturesUsed[i] != 0) {
401 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
402
403 intel_tex_unmap_images(intel, intel_texture_object(texObj));
404 }
405 }
406 }
407
408 typedef void (*span_init_func)(struct gl_renderbuffer *rb);
409
410 static span_init_func intel_span_init_funcs[MESA_FORMAT_COUNT] =
411 {
412 [MESA_FORMAT_A8] = intel_InitPointers_A8,
413 [MESA_FORMAT_RGB565] = intel_InitPointers_RGB565,
414 [MESA_FORMAT_ARGB4444] = intel_InitPointers_ARGB4444,
415 [MESA_FORMAT_ARGB1555] = intel_InitPointers_ARGB1555,
416 [MESA_FORMAT_XRGB8888] = intel_InitPointers_xRGB8888,
417 [MESA_FORMAT_ARGB8888] = intel_InitPointers_ARGB8888,
418 [MESA_FORMAT_SARGB8] = intel_InitPointers_ARGB8888,
419 [MESA_FORMAT_Z16] = _swrast_set_renderbuffer_accessors,
420 [MESA_FORMAT_X8_Z24] = _swrast_set_renderbuffer_accessors,
421 [MESA_FORMAT_S8_Z24] = _swrast_set_renderbuffer_accessors,
422 [MESA_FORMAT_S8] = _swrast_set_renderbuffer_accessors,
423 [MESA_FORMAT_R8] = _swrast_set_renderbuffer_accessors,
424 [MESA_FORMAT_GR88] = _swrast_set_renderbuffer_accessors,
425 [MESA_FORMAT_R16] = _swrast_set_renderbuffer_accessors,
426 [MESA_FORMAT_RG1616] = _swrast_set_renderbuffer_accessors,
427 [MESA_FORMAT_RGBA_FLOAT32] = _swrast_set_renderbuffer_accessors,
428 [MESA_FORMAT_RG_FLOAT32] = _swrast_set_renderbuffer_accessors,
429 [MESA_FORMAT_R_FLOAT32] = _swrast_set_renderbuffer_accessors,
430 [MESA_FORMAT_INTENSITY_FLOAT32] = _swrast_set_renderbuffer_accessors,
431 [MESA_FORMAT_LUMINANCE_FLOAT32] = _swrast_set_renderbuffer_accessors,
432 };
433
434 bool
435 intel_span_supports_format(gl_format format)
436 {
437 /* Rendering to/from integer textures will be done using MapRenderbuffer,
438 * rather than coding up new paths through GetRow/PutRow(), so claim support
439 * for those formats in here for now.
440 */
441 return (intel_span_init_funcs[format] != NULL ||
442 _mesa_is_format_integer_color(format));
443 }
444
445 /**
446 * Plug in appropriate span read/write functions for the given renderbuffer.
447 * These are used for the software fallbacks.
448 */
449 static void
450 intel_set_span_functions(struct intel_context *intel,
451 struct gl_renderbuffer *rb)
452 {
453 struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
454
455 assert(intel_span_init_funcs[irb->Base.Format]);
456 intel_span_init_funcs[irb->Base.Format](rb);
457
458 if (rb->DataType == GL_NONE) {
459 _mesa_problem(NULL,
460 "renderbuffer format %s is missing "
461 "intel_mesa_format_to_rb_datatype() support.",
462 _mesa_get_format_name(rb->Format));
463 }
464 }