summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStéphane Marchesin <marcheu@chromium.org>2012-06-25 19:45:56 -0700
committerStéphane Marchesin <marcheu@chromium.org>2012-06-26 23:18:15 -0700
commit45fc069600ddbfe07a0a0cd5280161a8c7c55dd0 (patch)
tree46b57b85495b4f09b588fed561db7da7e8562077
parent3bc39414ab960ecd77662e41c8df751c2c9c8984 (diff)
i915g: Implement sRGB textures
Since we don't have them in hw we emulate them in the shader. Although not recommended by the spec it is legit. As a side effect we also get GL 2.1. I think this is as far as we can take the i915.
-rw-r--r--src/gallium/drivers/i915/i915_context.h2
-rw-r--r--src/gallium/drivers/i915/i915_screen.c5
-rw-r--r--src/gallium/drivers/i915/i915_state_emit.c128
-rw-r--r--src/gallium/drivers/i915/i915_state_sampler.c3
-rw-r--r--src/gallium/drivers/i915/i915_state_static.c2
5 files changed, 128 insertions, 12 deletions
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index b019c9f342a..16b0c57166d 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -155,6 +155,8 @@ struct i915_state
155 unsigned sampler[I915_TEX_UNITS][3]; 155 unsigned sampler[I915_TEX_UNITS][3];
156 unsigned sampler_enable_flags; 156 unsigned sampler_enable_flags;
157 unsigned sampler_enable_nr; 157 unsigned sampler_enable_nr;
158 boolean sampler_srgb[I915_TEX_UNITS];
159 int srgb_const_offset;
158 160
159 /* texture image buffers */ 161 /* texture image buffers */
160 unsigned texbuffer[I915_TEX_UNITS][2]; 162 unsigned texbuffer[I915_TEX_UNITS][2];
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
index 9f293392f81..ff352035fb0 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -110,7 +110,9 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha
110 return PIPE_MAX_VERTEX_SAMPLERS; 110 return PIPE_MAX_VERTEX_SAMPLERS;
111 else 111 else
112 return 0; 112 return 0;
113 default: 113 case PIPE_SHADER_CAP_INTEGERS:
114 return 1;
115 default:
114 return draw_get_shader_param(shader, cap); 116 return draw_get_shader_param(shader, cap);
115 } 117 }
116 case PIPE_SHADER_FRAGMENT: 118 case PIPE_SHADER_FRAGMENT:
@@ -290,6 +292,7 @@ i915_is_format_supported(struct pipe_screen *screen,
290{ 292{
291 static const enum pipe_format tex_supported[] = { 293 static const enum pipe_format tex_supported[] = {
292 PIPE_FORMAT_B8G8R8A8_UNORM, 294 PIPE_FORMAT_B8G8R8A8_UNORM,
295 PIPE_FORMAT_B8G8R8A8_SRGB,
293 PIPE_FORMAT_B8G8R8X8_UNORM, 296 PIPE_FORMAT_B8G8R8X8_UNORM,
294 PIPE_FORMAT_R8G8B8A8_UNORM, 297 PIPE_FORMAT_R8G8B8A8_UNORM,
295 PIPE_FORMAT_R8G8B8X8_UNORM, 298 PIPE_FORMAT_R8G8B8X8_UNORM,
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 8ab8fb8cd74..ac999792c06 100644
--- a/src/gallium/drivers/i915/i915_state_emit.c
+++ b/src/gallium/drivers/i915/i915_state_emit.c
@@ -30,6 +30,7 @@
30#include "i915_context.h" 30#include "i915_context.h"
31#include "i915_batch.h" 31#include "i915_batch.h"
32#include "i915_debug.h" 32#include "i915_debug.h"
33#include "i915_fpc.h"
33#include "i915_resource.h" 34#include "i915_resource.h"
34 35
35#include "pipe/p_context.h" 36#include "pipe/p_context.h"
@@ -313,11 +314,42 @@ emit_sampler(struct i915_context *i915)
313 } 314 }
314} 315}
315 316
317static boolean is_tex_instruction(uint32_t* instruction)
318{
319 uint32_t op = instruction[0] &0xFF000000;
320 return ( (op == T0_TEXLD) ||
321 (op == T0_TEXLDP) ||
322 (op == T0_TEXLDB));
323}
324
325static uint32_t tex_sampler(uint32_t* instruction)
326{
327 return ( instruction[0] & T0_SAMPLER_NR_MASK);
328}
329
330static uint additional_constants(struct i915_context *i915)
331{
332 int i;
333
334 for (i = 0 ; i < i915->fs->program_len; i+=3) {
335 if ( is_tex_instruction(i915->fs->program + i)) {
336 int sampler = tex_sampler(i915->fs->program + i);
337 assert(sampler < I915_TEX_UNITS);
338 if ( i915->current.sampler_srgb[sampler] )
339 return 1;
340 }
341 }
342 return 0;
343}
344
316static void 345static void
317validate_constants(struct i915_context *i915, unsigned *batch_space) 346validate_constants(struct i915_context *i915, unsigned *batch_space)
318{ 347{
319 *batch_space = i915->fs->num_constants ? 348 int nr = i915->fs->num_constants ?
320 2 + 4*i915->fs->num_constants : 0; 349 2 + 4*i915->fs->num_constants : 0;
350
351 nr += 4*additional_constants(i915);
352 *batch_space = nr;
321} 353}
322 354
323static void 355static void
@@ -326,8 +358,11 @@ emit_constants(struct i915_context *i915)
326 /* Collate the user-defined constants with the fragment shader's 358 /* Collate the user-defined constants with the fragment shader's
327 * immediates according to the constant_flags[] array. 359 * immediates according to the constant_flags[] array.
328 */ 360 */
329 const uint nr = i915->fs->num_constants; 361 const uint nr = i915->fs->num_constants + additional_constants(i915);
362
363 assert(nr < I915_MAX_CONSTANT);
330 if (nr) { 364 if (nr) {
365 const float srgb_constants[4] = {1.0/1.055, 0.055/1.055, 2.4, 0.0822};
331 uint i; 366 uint i;
332 367
333 OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) ); 368 OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) );
@@ -340,9 +375,16 @@ emit_constants(struct i915_context *i915)
340 c = (uint *) i915_buffer(i915->constants[PIPE_SHADER_FRAGMENT])->data; 375 c = (uint *) i915_buffer(i915->constants[PIPE_SHADER_FRAGMENT])->data;
341 c += 4 * i; 376 c += 4 * i;
342 } 377 }
343 else { 378 else if (i < i915->fs->num_constants) {
344 /* emit program constant */ 379 /* emit program constant */
345 c = (uint *) i915->fs->constants[i]; 380 c = (uint *) i915->fs->constants[i];
381 } else {
382 /* emit constants for sRGB */
383
384 /* save const position in context for use in shader emit */
385 i915->current.srgb_const_offset = i;
386
387 c = (uint *) srgb_constants;
346 } 388 }
347#if 0 /* debug */ 389#if 0 /* debug */
348 { 390 {
@@ -363,18 +405,74 @@ emit_constants(struct i915_context *i915)
363static void 405static void
364validate_program(struct i915_context *i915, unsigned *batch_space) 406validate_program(struct i915_context *i915, unsigned *batch_space)
365{ 407{
366 uint additional_size = i915->current.target_fixup_format ? 1 : 0; 408 uint additional_size = 0, i;
409
410 additional_size += i915->current.target_fixup_format ? 3 : 0;
367 411
368 /* we need more batch space if we want to emulate rgba framebuffers */ 412 for (i = 0 ; i < i915->fs->program_len; i+=3)
369 *batch_space = i915->fs->decl_len + i915->fs->program_len + 3 * additional_size; 413 if ( is_tex_instruction(i915->fs->program + i) &&
414 i915->current.sampler_srgb[tex_sampler(i915->fs->program+i)] )
415 additional_size += 3 * 8 /* 8 instructions for srgb emulation */;
416
417 /* we need more batch space if we want to emulate rgba framebuffers
418 * or sRGB textures */
419 *batch_space = i915->fs->decl_len + i915->fs->program_len + additional_size;
420}
421
422static void emit_instruction(struct i915_context *i915,
423 int op,
424 int dst_mask,
425 int dst_reg,
426 int src0_reg,
427 int src1_reg,
428 int src2_reg)
429{
430 OUT_BATCH(op |
431 dst_mask |
432 0 | /* saturate */
433 A0_DEST(dst_reg) |
434 A0_SRC0(src0_reg)
435 );
436 OUT_BATCH(A1_SRC0(src0_reg) | A1_SRC1(src1_reg));
437 OUT_BATCH(A2_SRC1(src1_reg) | A2_SRC2(src2_reg));
438}
439
440static void
441emit_srgb_fixup(struct i915_context *i915,
442 uint *program)
443{
444 int dst_reg =
445 (program[0] & UREG_TYPE_NR_MASK) >> UREG_A0_DEST_SHIFT_LEFT;
446 int dst_mask = program[0] & A0_DEST_CHANNEL_ALL;
447 int cst_idx = i915->current.srgb_const_offset;
448 int cst0_reg = swizzle(UREG(REG_TYPE_CONST, cst_idx), X, X, X, X);
449 int cst1_reg = swizzle(UREG(REG_TYPE_CONST, cst_idx), Y, Y, Y, Y);
450 int cst2_reg = swizzle(UREG(REG_TYPE_CONST, cst_idx), Z, Z, Z, Z);
451 int t1_reg = UREG(REG_TYPE_R, 1);
452 int t1x_reg = swizzle(UREG(REG_TYPE_R, 1), X, X, X, X);
453 int t1y_reg = swizzle(UREG(REG_TYPE_R, 1), Y, Y, Y, Y);
454 int t1z_reg = swizzle(UREG(REG_TYPE_R, 1), Z, Z, Z, Z);
455
456 emit_instruction(i915, A0_MAD, A0_DEST_CHANNEL_ALL, t1_reg, dst_reg, cst0_reg, cst1_reg);
457 emit_instruction(i915, A0_LOG, A0_DEST_CHANNEL_X, t1_reg, t1x_reg, 0, 0);
458 emit_instruction(i915, A0_LOG, A0_DEST_CHANNEL_Y, t1_reg, t1y_reg, 0, 0);
459 emit_instruction(i915, A0_LOG, A0_DEST_CHANNEL_Z, t1_reg, t1z_reg, 0, 0);
460 emit_instruction(i915, A0_MUL, A0_DEST_CHANNEL_ALL, t1_reg, t1_reg, cst2_reg, 0);
461 emit_instruction(i915, A0_EXP, dst_mask & A0_DEST_CHANNEL_X, dst_reg, t1x_reg, 0, 0);
462 emit_instruction(i915, A0_EXP, dst_mask & A0_DEST_CHANNEL_Y, dst_reg, t1y_reg, 0, 0);
463 emit_instruction(i915, A0_EXP, dst_mask & A0_DEST_CHANNEL_Z, dst_reg, t1z_reg, 0, 0);
370} 464}
371 465
372static void 466static void
373emit_program(struct i915_context *i915) 467emit_program(struct i915_context *i915)
374{ 468{
375 uint need_target_fixup = i915->current.target_fixup_format ? 1 : 0; 469 uint additional_size = 0;
376 uint i; 470 uint i;
377 471
472 /* count how much additional space we'll need */
473 validate_program(i915, &additional_size);
474 additional_size -= i915->fs->decl_len + i915->fs->program_len;
475
378 /* we should always have, at least, a pass-through program */ 476 /* we should always have, at least, a pass-through program */
379 assert(i915->fs->program_len > 0); 477 assert(i915->fs->program_len > 0);
380 478
@@ -382,7 +480,7 @@ emit_program(struct i915_context *i915)
382 { 480 {
383 /* first word has the size, we have to adjust that */ 481 /* first word has the size, we have to adjust that */
384 uint size = (i915->fs->decl[0]); 482 uint size = (i915->fs->decl[0]);
385 size += need_target_fixup * 3; 483 size += additional_size;
386 OUT_BATCH(size); 484 OUT_BATCH(size);
387 } 485 }
388 486
@@ -390,11 +488,21 @@ emit_program(struct i915_context *i915)
390 OUT_BATCH(i915->fs->decl[i]); 488 OUT_BATCH(i915->fs->decl[i]);
391 489
392 /* output the program */ 490 /* output the program */
393 for (i = 0 ; i < i915->fs->program_len; i++) 491 assert(i915->fs->program_len % 3 == 0);
492 for (i = 0 ; i < i915->fs->program_len; i+=3) {
394 OUT_BATCH(i915->fs->program[i]); 493 OUT_BATCH(i915->fs->program[i]);
494 OUT_BATCH(i915->fs->program[i+1]);
495 OUT_BATCH(i915->fs->program[i+2]);
496
497 /* TEX fixup for sRGB */
498 if ( is_tex_instruction(i915->fs->program+i) &&
499 i915->current.sampler_srgb[tex_sampler(i915->fs->program+i)] )
500 emit_srgb_fixup(i915, i915->fs->program);
501
502 }
395 503
396 /* we emit an additional mov with swizzle to fake RGBA framebuffers */ 504 /* we emit an additional mov with swizzle to fake RGBA framebuffers */
397 if (need_target_fixup) { 505 if (i915->current.target_fixup_format) {
398 /* mov out_color, out_color.zyxw */ 506 /* mov out_color, out_color.zyxw */
399 OUT_BATCH(A0_MOV | 507 OUT_BATCH(A0_MOV |
400 (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) | 508 (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c
index 19d3c83ffcd..9aba68afbca 100644
--- a/src/gallium/drivers/i915/i915_state_sampler.c
+++ b/src/gallium/drivers/i915/i915_state_sampler.c
@@ -215,6 +215,7 @@ static uint translate_texture_format(enum pipe_format pipeFormat,
215 case PIPE_FORMAT_B10G10R10A2_UNORM: 215 case PIPE_FORMAT_B10G10R10A2_UNORM:
216 return MAPSURF_32BIT | MT_32BIT_ARGB2101010; 216 return MAPSURF_32BIT | MT_32BIT_ARGB2101010;
217 case PIPE_FORMAT_B8G8R8A8_UNORM: 217 case PIPE_FORMAT_B8G8R8A8_UNORM:
218 case PIPE_FORMAT_B8G8R8A8_SRGB:
218 return MAPSURF_32BIT | MT_32BIT_ARGB8888; 219 return MAPSURF_32BIT | MT_32BIT_ARGB8888;
219 case PIPE_FORMAT_B8G8R8X8_UNORM: 220 case PIPE_FORMAT_B8G8R8X8_UNORM:
220 return MAPSURF_32BIT | MT_32BIT_XRGB8888; 221 return MAPSURF_32BIT | MT_32BIT_XRGB8888;
@@ -309,6 +310,8 @@ static void update_map(struct i915_context *i915,
309 assert(depth); 310 assert(depth);
310 311
311 format = translate_texture_format(pt->format, view); 312 format = translate_texture_format(pt->format, view);
313 i915->current.sampler_srgb[unit] = ( pt->format == PIPE_FORMAT_B8G8R8A8_SRGB ||
314 pt->format == PIPE_FORMAT_L8_SRGB );
312 pitch = tex->stride; 315 pitch = tex->stride;
313 316
314 assert(format); 317 assert(format);
diff --git a/src/gallium/drivers/i915/i915_state_static.c b/src/gallium/drivers/i915/i915_state_static.c
index 9587dec4b90..4d020975576 100644
--- a/src/gallium/drivers/i915/i915_state_static.c
+++ b/src/gallium/drivers/i915/i915_state_static.c
@@ -31,7 +31,6 @@
31#include "i915_screen.h" 31#include "i915_screen.h"
32 32
33 33
34
35/*********************************************************************** 34/***********************************************************************
36 * Update framebuffer state 35 * Update framebuffer state
37 */ 36 */
@@ -39,6 +38,7 @@ static unsigned translate_format(enum pipe_format format)
39{ 38{
40 switch (format) { 39 switch (format) {
41 case PIPE_FORMAT_B8G8R8A8_UNORM: 40 case PIPE_FORMAT_B8G8R8A8_UNORM:
41 case PIPE_FORMAT_B8G8R8A8_SRGB:
42 case PIPE_FORMAT_B8G8R8X8_UNORM: 42 case PIPE_FORMAT_B8G8R8X8_UNORM:
43 case PIPE_FORMAT_R8G8B8A8_UNORM: 43 case PIPE_FORMAT_R8G8B8A8_UNORM:
44 case PIPE_FORMAT_R8G8B8X8_UNORM: 44 case PIPE_FORMAT_R8G8B8X8_UNORM: