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