5045c9b4a66f255167aa2288be1bf0b4a58fbf4b
[mesa.git] / src / gallium / drivers / i965 / brw_wm_surface_state.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a 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, sublicense, 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
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 */
31
32
33 #include "intel_mipmap_tree.h"
34 #include "brw_batchbuffer.h"
35 #include "intel_tex.h"
36 #include "intel_fbo.h"
37
38 #include "brw_context.h"
39 #include "brw_state.h"
40 #include "brw_defines.h"
41
42
43 static GLuint translate_tex_target( GLenum target )
44 {
45 switch (target) {
46 case GL_TEXTURE_1D:
47 return BRW_SURFACE_1D;
48
49 case GL_TEXTURE_RECTANGLE_NV:
50 return BRW_SURFACE_2D;
51
52 case GL_TEXTURE_2D:
53 return BRW_SURFACE_2D;
54
55 case GL_TEXTURE_3D:
56 return BRW_SURFACE_3D;
57
58 case GL_TEXTURE_CUBE_MAP:
59 return BRW_SURFACE_CUBE;
60
61 default:
62 assert(0);
63 return 0;
64 }
65 }
66
67
68 static GLuint translate_tex_format( GLuint mesa_format,
69 GLenum depth_mode )
70 {
71 switch( pipe_format ) {
72 case PIPE_FORMAT_L8_UNORM:
73 return BRW_SURFACEFORMAT_L8_UNORM;
74
75 case PIPE_FORMAT_I8_UNORM:
76 return BRW_SURFACEFORMAT_I8_UNORM;
77
78 case PIPE_FORMAT_A8_UNORM:
79 return BRW_SURFACEFORMAT_A8_UNORM;
80
81 case PIPE_FORMAT_A8L8_UNORM:
82 return BRW_SURFACEFORMAT_L8A8_UNORM;
83
84 case PIPE_FORMAT_A8R8G8B8_UNORM:
85 case PIPE_FORMAT_B8G8R8A8_UNORM:
86 case PIPE_FORMAT_R8G8B8A8_UNORM:
87 return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
88
89 case PIPE_FORMAT_R8G8B8X8_UNORM:
90 return BRW_SURFACEFORMAT_R8G8B8X8_UNORM;
91
92 case PIPE_FORMAT_:
93 return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
94
95 case PIPE_FORMAT_RGB565:
96 return BRW_SURFACEFORMAT_B5G6R5_UNORM;
97
98 case PIPE_FORMAT_ARGB1555:
99 return BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
100
101 case PIPE_FORMAT_ARGB4444:
102 return BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
103
104
105 case PIPE_FORMAT_L16_UNORM:
106 return BRW_SURFACEFORMAT_L16_UNORM;
107
108 case PIPE_FORMAT_I16_UNORM:
109 return BRW_SURFACEFORMAT_I16_UNORM;
110
111 case PIPE_FORMAT_A16_UNORM:
112 return BRW_SURFACEFORMAT_A16_UNORM;
113
114 case PIPE_FORMAT_YCBCR_REV:
115 return BRW_SURFACEFORMAT_YCRCB_NORMAL;
116
117 case PIPE_FORMAT_YCBCR:
118 return BRW_SURFACEFORMAT_YCRCB_SWAPUVY;
119
120 case PIPE_FORMAT_RGB_FXT1:
121 case PIPE_FORMAT_RGBA_FXT1:
122 return BRW_SURFACEFORMAT_FXT1;
123
124 case PIPE_FORMAT_RGB_DXT1:
125 return BRW_SURFACEFORMAT_DXT1_RGB;
126
127 case PIPE_FORMAT_RGBA_DXT1:
128 return BRW_SURFACEFORMAT_BC1_UNORM;
129
130 case PIPE_FORMAT_RGBA_DXT3:
131 return BRW_SURFACEFORMAT_BC2_UNORM;
132
133 case PIPE_FORMAT_RGBA_DXT5:
134 return BRW_SURFACEFORMAT_BC3_UNORM;
135
136 case PIPE_FORMAT_R8G8B8A8_SRGB:
137 return BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB;
138
139 case PIPE_FORMAT_A8L8_SRGB:
140 return BRW_SURFACEFORMAT_L8A8_UNORM_SRGB;
141
142 case PIPE_FORMAT_L8_SRGB:
143 return BRW_SURFACEFORMAT_L8_UNORM_SRGB;
144
145 case PIPE_FORMAT_SRGB_DXT1:
146 return BRW_SURFACEFORMAT_BC1_UNORM_SRGB;
147
148 case PIPE_FORMAT_S8_Z24:
149 /* XXX: these different surface formats don't seem to
150 * make any difference for shadow sampler/compares.
151 */
152 if (depth_mode == GL_INTENSITY)
153 return BRW_SURFACEFORMAT_I24X8_UNORM;
154 else if (depth_mode == GL_ALPHA)
155 return BRW_SURFACEFORMAT_A24X8_UNORM;
156 else
157 return BRW_SURFACEFORMAT_L24X8_UNORM;
158
159 case PIPE_FORMAT_DUDV8:
160 return BRW_SURFACEFORMAT_R8G8_SNORM;
161
162 case PIPE_FORMAT_SIGNED_RGBA8888_REV:
163 return BRW_SURFACEFORMAT_R8G8B8A8_SNORM;
164
165 default:
166 assert(0);
167 return 0;
168 }
169 }
170
171 static void
172 brw_set_surface_tiling(struct brw_surface_state *surf, uint32_t tiling)
173 {
174 switch (tiling) {
175 case I915_TILING_NONE:
176 surf->ss3.tiled_surface = 0;
177 surf->ss3.tile_walk = 0;
178 break;
179 case I915_TILING_X:
180 surf->ss3.tiled_surface = 1;
181 surf->ss3.tile_walk = BRW_TILEWALK_XMAJOR;
182 break;
183 case I915_TILING_Y:
184 surf->ss3.tiled_surface = 1;
185 surf->ss3.tile_walk = BRW_TILEWALK_YMAJOR;
186 break;
187 }
188 }
189
190 static struct brw_winsys_buffer *
191 brw_create_texture_surface( struct brw_context *brw,
192 struct brw_surface_key *key )
193 {
194 struct brw_surface_state surf;
195 struct brw_winsys_buffer *bo;
196
197 memset(&surf, 0, sizeof(surf));
198
199 surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
200 surf.ss0.surface_type = translate_tex_target(key->target);
201 if (key->bo) {
202 surf.ss0.surface_format = translate_tex_format(key->format,
203 key->internal_format,
204 key->depthmode);
205 }
206 else {
207 switch (key->depth) {
208 case 32:
209 surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
210 break;
211 default:
212 case 24:
213 surf.ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8X8_UNORM;
214 break;
215 case 16:
216 surf.ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
217 break;
218 }
219 }
220
221 /* This is ok for all textures with channel width 8bit or less:
222 */
223 /* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
224 if (key->bo)
225 surf.ss1.base_addr = key->bo->offset; /* reloc */
226 else
227 surf.ss1.base_addr = key->offset;
228
229 surf.ss2.mip_count = key->last_level;
230 surf.ss2.width = key->width - 1;
231 surf.ss2.height = key->height - 1;
232 brw_set_surface_tiling(&surf, key->tiling);
233 surf.ss3.pitch = (key->pitch * key->cpp) - 1;
234 surf.ss3.depth = key->depth - 1;
235
236 surf.ss4.min_lod = 0;
237
238 if (key->target == GL_TEXTURE_CUBE_MAP) {
239 surf.ss0.cube_pos_x = 1;
240 surf.ss0.cube_pos_y = 1;
241 surf.ss0.cube_pos_z = 1;
242 surf.ss0.cube_neg_x = 1;
243 surf.ss0.cube_neg_y = 1;
244 surf.ss0.cube_neg_z = 1;
245 }
246
247 bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
248 key, sizeof(*key),
249 &key->bo, key->bo ? 1 : 0,
250 &surf, sizeof(surf),
251 NULL, NULL);
252
253 if (key->bo) {
254 /* Emit relocation to surface contents */
255 dri_bo_emit_reloc(bo,
256 I915_GEM_DOMAIN_SAMPLER, 0,
257 0,
258 offsetof(struct brw_surface_state, ss1),
259 key->bo);
260 }
261 return bo;
262 }
263
264 static void
265 brw_update_texture_surface( struct brw_context *brw, GLuint unit )
266 {
267 struct pipe_texture *tex = brw->texture[unit];
268 struct brw_surface_key key;
269 const GLuint surf = SURF_INDEX_TEXTURE(unit);
270
271 memset(&key, 0, sizeof(key));
272
273 key.format = tex->base.format;
274 key.pitch = tex->pitch;
275 key.depth = tex->base.depth[0];
276 key.bo = tex->buffer;
277 key.offset = 0;
278
279 key.target = tObj->target; /* translated to BRW enum */
280 /* key.depthmode = tObj->DepthMode; */ /* XXX: add this to gallium? or the state tracker? */
281 key.first_level = 0;
282 key.last_level = tex->base.last_level;
283 key.width = tex->base.depth[0];
284 key.height = tex->base.height[0];
285 key.cpp = tex->cpp;
286 key.tiling = tex->tiling;
287
288 brw->sws->bo_unreference(brw->wm.surf_bo[surf]);
289 brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache,
290 BRW_SS_SURFACE,
291 &key, sizeof(key),
292 &key.bo, key.bo ? 1 : 0,
293 NULL);
294 if (brw->wm.surf_bo[surf] == NULL) {
295 brw->wm.surf_bo[surf] = brw_create_texture_surface(brw, &key);
296 }
297 }
298
299
300
301 /**
302 * Create the constant buffer surface. Vertex/fragment shader constants will be
303 * read from this buffer with Data Port Read instructions/messages.
304 */
305 struct brw_winsys_buffer *
306 brw_create_constant_surface( struct brw_context *brw,
307 struct brw_surface_key *key )
308 {
309 const GLint w = key->width - 1;
310 struct brw_surface_state surf;
311 struct brw_winsys_buffer *bo;
312
313 memset(&surf, 0, sizeof(surf));
314
315 surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
316 surf.ss0.surface_type = BRW_SURFACE_BUFFER;
317 surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
318
319 assert(key->bo);
320 if (key->bo)
321 surf.ss1.base_addr = key->bo->offset; /* reloc */
322 else
323 surf.ss1.base_addr = key->offset;
324
325 surf.ss2.width = w & 0x7f; /* bits 6:0 of size or width */
326 surf.ss2.height = (w >> 7) & 0x1fff; /* bits 19:7 of size or width */
327 surf.ss3.depth = (w >> 20) & 0x7f; /* bits 26:20 of size or width */
328 surf.ss3.pitch = (key->pitch * key->cpp) - 1; /* ignored?? */
329 brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */
330
331 bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
332 key, sizeof(*key),
333 &key->bo, key->bo ? 1 : 0,
334 &surf, sizeof(surf),
335 NULL, NULL);
336
337 if (key->bo) {
338 /* Emit relocation to surface contents */
339 dri_bo_emit_reloc(bo,
340 I915_GEM_DOMAIN_SAMPLER, 0,
341 0,
342 offsetof(struct brw_surface_state, ss1),
343 key->bo);
344 }
345
346 return bo;
347 }
348
349 /* Creates a new WM constant buffer reflecting the current fragment program's
350 * constants, if needed by the fragment program.
351 *
352 * Otherwise, constants go through the CURBEs using the brw_constant_buffer
353 * state atom.
354 */
355 static drm_intel_bo *
356 brw_wm_update_constant_buffer(struct brw_context *brw)
357 {
358 struct brw_fragment_program *fp =
359 (struct brw_fragment_program *) brw->fragment_program;
360 const struct gl_program_parameter_list *params = fp->program.Base.Parameters;
361 const int size = params->NumParameters * 4 * sizeof(GLfloat);
362 drm_intel_bo *const_buffer;
363
364 /* BRW_NEW_FRAGMENT_PROGRAM */
365 if (!fp->use_const_buffer)
366 return NULL;
367
368 const_buffer = drm_intel_bo_alloc(intel->bufmgr, "fp_const_buffer",
369 size, 64);
370
371 /* _NEW_PROGRAM_CONSTANTS */
372 dri_bo_subdata(const_buffer, 0, size, params->ParameterValues);
373
374 return const_buffer;
375 }
376
377 /**
378 * Update the surface state for a WM constant buffer.
379 * The constant buffer will be (re)allocated here if needed.
380 */
381 static void
382 brw_update_wm_constant_surface( struct brw_context *brw,
383 GLuint surf)
384 {
385 struct brw_context *brw = brw_context(ctx);
386 struct brw_surface_key key;
387 struct brw_fragment_program *fp =
388 (struct brw_fragment_program *) brw->fragment_program;
389 const struct gl_program_parameter_list *params =
390 fp->program.Base.Parameters;
391
392 /* If we're in this state update atom, we need to update WM constants, so
393 * free the old buffer and create a new one for the new contents.
394 */
395 brw->sws->bo_unreference(fp->const_buffer);
396 fp->const_buffer = brw_wm_update_constant_buffer(brw);
397
398 /* If there's no constant buffer, then no surface BO is needed to point at
399 * it.
400 */
401 if (fp->const_buffer == 0) {
402 drm_intel_bo_unreference(brw->wm.surf_bo[surf]);
403 brw->wm.surf_bo[surf] = NULL;
404 return;
405 }
406
407 memset(&key, 0, sizeof(key));
408
409 key.format = PIPE_FORMAT_RGBA_FLOAT32;
410 key.internal_format = GL_RGBA;
411 key.bo = fp->const_buffer;
412 key.depthmode = GL_NONE;
413 key.pitch = params->NumParameters;
414 key.width = params->NumParameters;
415 key.height = 1;
416 key.depth = 1;
417 key.cpp = 16;
418
419 /*
420 printf("%s:\n", __FUNCTION__);
421 printf(" width %d height %d depth %d cpp %d pitch %d\n",
422 key.width, key.height, key.depth, key.cpp, key.pitch);
423 */
424
425 brw->sws->bo_unreference(brw->wm.surf_bo[surf]);
426 brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache,
427 BRW_SS_SURFACE,
428 &key, sizeof(key),
429 &key.bo, key.bo ? 1 : 0,
430 NULL);
431 if (brw->wm.surf_bo[surf] == NULL) {
432 brw->wm.surf_bo[surf] = brw_create_constant_surface(brw, &key);
433 }
434 brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
435 }
436
437 /**
438 * Updates surface / buffer for fragment shader constant buffer, if
439 * one is required.
440 *
441 * This consumes the state updates for the constant buffer, and produces
442 * BRW_NEW_WM_SURFACES to get picked up by brw_prepare_wm_surfaces for
443 * inclusion in the binding table.
444 */
445 static void prepare_wm_constant_surface(struct brw_context *brw )
446 {
447 struct brw_fragment_program *fp =
448 (struct brw_fragment_program *) brw->fragment_program;
449 GLuint surf = SURF_INDEX_FRAG_CONST_BUFFER;
450
451 drm_intel_bo_unreference(fp->const_buffer);
452 fp->const_buffer = brw_wm_update_constant_buffer(brw);
453
454 /* If there's no constant buffer, then no surface BO is needed to point at
455 * it.
456 */
457 if (fp->const_buffer == 0) {
458 if (brw->wm.surf_bo[surf] != NULL) {
459 drm_intel_bo_unreference(brw->wm.surf_bo[surf]);
460 brw->wm.surf_bo[surf] = NULL;
461 brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
462 }
463 return;
464 }
465
466 brw_update_wm_constant_surface(ctx, surf);
467 }
468
469 const struct brw_tracked_state brw_wm_constant_surface = {
470 .dirty = {
471 .mesa = (_NEW_PROGRAM_CONSTANTS),
472 .brw = (BRW_NEW_FRAGMENT_PROGRAM),
473 .cache = 0
474 },
475 .prepare = prepare_wm_constant_surface,
476 };
477
478
479 /**
480 * Sets up a surface state structure to point at the given region.
481 * While it is only used for the front/back buffer currently, it should be
482 * usable for further buffers when doing ARB_draw_buffer support.
483 */
484 static void
485 brw_update_renderbuffer_surface(struct brw_context *brw,
486 struct gl_renderbuffer *rb,
487 unsigned int unit)
488 {
489 struct brw_winsys_buffer *region_bo = NULL;
490 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
491 struct intel_region *region = irb ? irb->region : NULL;
492 struct {
493 unsigned int surface_type;
494 unsigned int surface_format;
495 unsigned int width, height, pitch, cpp;
496 GLubyte color_mask[4];
497 GLboolean color_blend;
498 uint32_t tiling;
499 uint32_t draw_offset;
500 } key;
501
502 memset(&key, 0, sizeof(key));
503
504 if (region != NULL) {
505 region_bo = region->buffer;
506
507 key.surface_type = BRW_SURFACE_2D;
508 switch (irb->texformat->MesaFormat) {
509 case PIPE_FORMAT_ARGB8888:
510 key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
511 break;
512 case PIPE_FORMAT_RGB565:
513 key.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM;
514 break;
515 case PIPE_FORMAT_ARGB1555:
516 key.surface_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
517 break;
518 case PIPE_FORMAT_ARGB4444:
519 key.surface_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
520 break;
521 default:
522 _mesa_problem(ctx, "Bad renderbuffer format: %d\n",
523 irb->texformat->MesaFormat);
524 }
525 key.tiling = region->tiling;
526 if (brw->intel.intelScreen->driScrnPriv->dri2.enabled) {
527 key.width = rb->Width;
528 key.height = rb->Height;
529 } else {
530 key.width = region->width;
531 key.height = region->height;
532 }
533 key.pitch = region->pitch;
534 key.cpp = region->cpp;
535 key.draw_offset = region->draw_offset; /* cur 3d or cube face offset */
536 } else {
537 key.surface_type = BRW_SURFACE_NULL;
538 key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
539 key.tiling = I915_TILING_X;
540 key.width = 1;
541 key.height = 1;
542 key.cpp = 4;
543 key.draw_offset = 0;
544 }
545 memcpy(key.color_mask, ctx->Color.ColorMask,
546 sizeof(key.color_mask));
547 key.color_blend = (!ctx->Color._LogicOpEnabled &&
548 ctx->Color.BlendEnabled);
549
550 brw->sws->bo_unreference(brw->wm.surf_bo[unit]);
551 brw->wm.surf_bo[unit] = brw_search_cache(&brw->surface_cache,
552 BRW_SS_SURFACE,
553 &key, sizeof(key),
554 &region_bo, 1,
555 NULL);
556
557 if (brw->wm.surf_bo[unit] == NULL) {
558 struct brw_surface_state surf;
559
560 memset(&surf, 0, sizeof(surf));
561
562 surf.ss0.surface_format = key.surface_format;
563 surf.ss0.surface_type = key.surface_type;
564 if (key.tiling == I915_TILING_NONE) {
565 surf.ss1.base_addr = key.draw_offset;
566 } else {
567 uint32_t tile_offset = key.draw_offset % 4096;
568
569 surf.ss1.base_addr = key.draw_offset - tile_offset;
570
571 assert(BRW_IS_G4X(brw) || tile_offset == 0);
572 if (BRW_IS_G4X(brw)) {
573 if (key.tiling == I915_TILING_X) {
574 /* Note that the low bits of these fields are missing, so
575 * there's the possibility of getting in trouble.
576 */
577 surf.ss5.x_offset = (tile_offset % 512) / key.cpp / 4;
578 surf.ss5.y_offset = tile_offset / 512 / 2;
579 } else {
580 surf.ss5.x_offset = (tile_offset % 128) / key.cpp / 4;
581 surf.ss5.y_offset = tile_offset / 128 / 2;
582 }
583 }
584 }
585 if (region_bo != NULL)
586 surf.ss1.base_addr += region_bo->offset; /* reloc */
587
588 surf.ss2.width = key.width - 1;
589 surf.ss2.height = key.height - 1;
590 brw_set_surface_tiling(&surf, key.tiling);
591 surf.ss3.pitch = (key.pitch * key.cpp) - 1;
592
593 /* _NEW_COLOR */
594 surf.ss0.color_blend = key.color_blend;
595 surf.ss0.writedisable_red = !key.color_mask[0];
596 surf.ss0.writedisable_green = !key.color_mask[1];
597 surf.ss0.writedisable_blue = !key.color_mask[2];
598 surf.ss0.writedisable_alpha = !key.color_mask[3];
599
600 /* Key size will never match key size for textures, so we're safe. */
601 brw->wm.surf_bo[unit] = brw_upload_cache(&brw->surface_cache,
602 BRW_SS_SURFACE,
603 &key, sizeof(key),
604 &region_bo, 1,
605 &surf, sizeof(surf),
606 NULL, NULL);
607 if (region_bo != NULL) {
608 /* We might sample from it, and we might render to it, so flag
609 * them both. We might be able to figure out from other state
610 * a more restrictive relocation to emit.
611 */
612 drm_intel_bo_emit_reloc(brw->wm.surf_bo[unit],
613 offsetof(struct brw_surface_state, ss1),
614 region_bo,
615 surf.ss1.base_addr - region_bo->offset,
616 I915_GEM_DOMAIN_RENDER,
617 I915_GEM_DOMAIN_RENDER);
618 }
619 }
620 }
621
622
623 /**
624 * Constructs the binding table for the WM surface state, which maps unit
625 * numbers to surface state objects.
626 */
627 static struct brw_winsys_buffer *
628 brw_wm_get_binding_table(struct brw_context *brw)
629 {
630 struct brw_winsys_buffer *bind_bo;
631
632 assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF);
633
634 bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
635 NULL, 0,
636 brw->wm.surf_bo, brw->wm.nr_surfaces,
637 NULL);
638
639 if (bind_bo == NULL) {
640 GLuint data_size = brw->wm.nr_surfaces * sizeof(GLuint);
641 uint32_t data[BRW_WM_MAX_SURF];
642 int i;
643
644 for (i = 0; i < brw->wm.nr_surfaces; i++)
645 if (brw->wm.surf_bo[i])
646 data[i] = brw->wm.surf_bo[i]->offset;
647 else
648 data[i] = 0;
649
650 bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
651 NULL, 0,
652 brw->wm.surf_bo, brw->wm.nr_surfaces,
653 data, data_size,
654 NULL, NULL);
655
656 /* Emit binding table relocations to surface state */
657 for (i = 0; i < BRW_WM_MAX_SURF; i++) {
658 if (brw->wm.surf_bo[i] != NULL) {
659 dri_bo_emit_reloc(bind_bo,
660 I915_GEM_DOMAIN_INSTRUCTION, 0,
661 0,
662 i * sizeof(GLuint),
663 brw->wm.surf_bo[i]);
664 }
665 }
666 }
667
668 return bind_bo;
669 }
670
671 static void prepare_wm_surfaces(struct brw_context *brw )
672 {
673 GLuint i;
674 int old_nr_surfaces;
675
676 /* _NEW_BUFFERS */
677 /* Update surfaces for drawing buffers */
678 if (ctx->DrawBuffer->_NumColorDrawBuffers >= 1) {
679 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
680 brw_update_renderbuffer_surface(brw,
681 ctx->DrawBuffer->_ColorDrawBuffers[i],
682 i);
683 }
684 } else {
685 brw_update_renderbuffer_surface(brw, NULL, 0);
686 }
687
688 old_nr_surfaces = brw->wm.nr_surfaces;
689 brw->wm.nr_surfaces = MAX_DRAW_BUFFERS;
690
691 if (brw->wm.surf_bo[SURF_INDEX_FRAG_CONST_BUFFER] != NULL)
692 brw->wm.nr_surfaces = SURF_INDEX_FRAG_CONST_BUFFER + 1;
693
694 /* Update surfaces for textures */
695 for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
696 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
697 const GLuint surf = SURF_INDEX_TEXTURE(i);
698
699 /* _NEW_TEXTURE, BRW_NEW_TEXDATA */
700 if (texUnit->_ReallyEnabled) {
701 brw_update_texture_surface(ctx, i);
702 brw->wm.nr_surfaces = surf + 1;
703 } else {
704 brw->sws->bo_unreference(brw->wm.surf_bo[surf]);
705 brw->wm.surf_bo[surf] = NULL;
706 }
707 }
708
709 brw->sws->bo_unreference(brw->wm.bind_bo);
710 brw->wm.bind_bo = brw_wm_get_binding_table(brw);
711
712 if (brw->wm.nr_surfaces != old_nr_surfaces)
713 brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES;
714 }
715
716 const struct brw_tracked_state brw_wm_surfaces = {
717 .dirty = {
718 .mesa = (_NEW_COLOR |
719 _NEW_TEXTURE |
720 _NEW_BUFFERS),
721 .brw = (BRW_NEW_CONTEXT |
722 BRW_NEW_WM_SURFACES),
723 .cache = 0
724 },
725 .prepare = prepare_wm_surfaces,
726 };
727
728
729