diff options
author | Stéphane Marchesin <marcheu@chromium.org> | 2012-06-25 19:45:56 -0700 |
---|---|---|
committer | Stéphane Marchesin <marcheu@chromium.org> | 2012-06-26 23:18:15 -0700 |
commit | 45fc069600ddbfe07a0a0cd5280161a8c7c55dd0 (patch) | |
tree | 46b57b85495b4f09b588fed561db7da7e8562077 | |
parent | 3bc39414ab960ecd77662e41c8df751c2c9c8984 (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.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_screen.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_state_emit.c | 128 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_state_sampler.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_state_static.c | 2 |
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 | ||
317 | static 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 | |||
325 | static uint32_t tex_sampler(uint32_t* instruction) | ||
326 | { | ||
327 | return ( instruction[0] & T0_SAMPLER_NR_MASK); | ||
328 | } | ||
329 | |||
330 | static 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 | |||
316 | static void | 345 | static void |
317 | validate_constants(struct i915_context *i915, unsigned *batch_space) | 346 | validate_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 | ||
323 | static void | 355 | static 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) | |||
363 | static void | 405 | static void |
364 | validate_program(struct i915_context *i915, unsigned *batch_space) | 406 | validate_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 | |||
422 | static 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 | |||
440 | static void | ||
441 | emit_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 | ||
372 | static void | 466 | static void |
373 | emit_program(struct i915_context *i915) | 467 | emit_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: |