* Finally the overlay looks like an overlay. It took me almost a day to realize that

the Intel chip obviously cannot do overlays in B_RGB16 - even though it pretends
  to be able to do that.
* B_YCbCr422 seems to work, though, I haven't tested any other spaces for now, and
  I somewhat doubt they will work. It's all green, though, and the scaling doesn't
  seem to be correct - that we be solvable, though :)
* There aren't any bounds checks (so don't move the window out of the screen), and
  also the overlay_view offsets are ignored.
* Scaling and moving is now detected, and there is always as little work done as
  possible to reduce the workload on buffer switches (the most common case).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17315 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-05-04 09:08:26 +00:00
parent 3279f3b055
commit 6a3543db2a
3 changed files with 150 additions and 58 deletions
@@ -218,6 +218,7 @@ struct intel_free_graphics_memory {
#define COMMAND_OVERLAY_CONTINUE (0 << 21)
#define COMMAND_OVERLAY_ON (1 << 21)
#define COMMAND_OVERLAY_OFF (2 << 21)
#define OVERLAY_UPDATE_COEFFICIENTS 0x1
// overlay
@@ -233,13 +234,21 @@ struct intel_free_graphics_memory {
#define INTEL_OVERLAY_GAMMA_0 0x30024
struct overlay_scale {
uint32 vertical_scale_fraction : 12;
uint32 _reserved0 : 1;
uint32 horizontal_downscale_factor : 3;
uint32 _reserved1 : 1;
uint32 _reserved0 : 3;
uint32 horizontal_scale_fraction : 12;
uint32 _reserved1 : 1;
uint32 horizontal_downscale_factor : 3;
uint32 _reserved2 : 1;
uint32 vertical_scale_fraction : 12;
};
#define OVERLAY_FORMAT_RGB15 0x2
#define OVERLAY_FORMAT_RGB16 0x3
#define OVERLAY_FORMAT_RGB32 0x1
#define OVERLAY_FORMAT_YCbCr422 0x8
#define OVERLAY_FORMAT_YCbCr411 0x9
#define OVERLAY_FORMAT_YCbCr420 0xc
// The real overlay registers are written to using an update buffer
struct overlay_registers {
@@ -249,14 +258,19 @@ struct overlay_registers {
uint32 buffer_v0;
uint32 buffer_u1;
uint32 buffer_v1;
// (0x18) OSTRIDE - overlay stride
uint16 stride_rgb;
uint16 stride_uv;
// (0x1c) YRGB_VPH - Y/RGB vertical phase
uint16 vertical_phase0_rgb;
uint16 vertical_phase1_rgb;
// (0x20) UV_VPH - UV vertical phase
uint16 vertical_phase0_uv;
uint16 vertical_phase1_uv;
// (0x24) HORZ_PH - horizontal phase
uint16 horizontal_phase_rgb;
uint16 horizontal_phase_uv;
// (0x28) INIT_PHS - initial phase shift
uint32 initial_vertical_phase0_shift_rgb0 : 4;
uint32 initial_vertical_phase1_shift_rgb0 : 4;
uint32 initial_horizontal_phase_shift_rgb0 : 4;
@@ -264,12 +278,16 @@ struct overlay_registers {
uint32 initial_vertical_phase1_shift_uv : 4;
uint32 initial_horizontal_phase_shift_uv : 4;
uint32 _reserved0 : 8;
// (0x2c) DWINPOS - destination window position
uint16 window_left;
uint16 window_top;
// (0x30) DWINSZ - destination window size
uint16 window_width;
uint16 window_height;
// (0x34) SWIDTH - source width
uint16 source_width_rgb;
uint16 source_width_uv;
// (0x38) SWITDHSW - source width in 8 byte steps
uint16 source_bytes_per_row_rgb;
uint16 source_bytes_per_row_uv;
uint16 source_height_rgb;
@@ -319,7 +337,8 @@ struct overlay_registers {
uint32 yuv_to_rgb_bypass : 1;
uint32 _reserved12 : 11;
uint32 gamma2_enabled : 1;
uint32 _reserved13 : 2;
uint32 _reserved13 : 1;
uint32 select_pipe : 1;
uint32 slot_time : 8;
uint32 _reserved14 : 5;
// (0x68) OCOMD - overlay command
@@ -332,7 +351,7 @@ struct overlay_registers {
uint32 tv_flip_field_enabled : 1;
uint32 _reserved16 : 1;
uint32 tv_flip_field_parity : 1;
uint32 _reserved17 : 4;
uint32 source_format : 4;
uint32 ycbcr422_order : 2;
uint32 _reserved18 : 1;
uint32 mirroring_mode : 2;
@@ -353,6 +372,18 @@ struct overlay_registers {
// (0xa4) UVSCALEV - vertical downscale
uint16 vertical_scale_rgb;
uint16 vertical_scale_uv;
uint32 _reserved22[86];
// (0x200) polyphase filter coefficients
uint16 vertical_coefficients_rgb[128];
uint16 horizontal_coefficients_rgb[128];
uint32 _reserved23[64];
// (0x500)
uint16 vertical_coefficients_uv[128];
uint16 horizontal_coefficients_uv[128];
};
//----------------------------------------------------------
@@ -20,6 +20,13 @@ struct overlay {
uint32 buffer_offset;
};
struct overlay_frame {
int16 h_start;
int16 v_start;
uint16 width;
uint16 height;
};
struct accelerant_info {
vuint8 *regs;
area_id regs_area;
@@ -34,6 +41,10 @@ struct accelerant_info {
struct overlay_registers *overlay_registers;
overlay *current_overlay;
overlay_view last_overlay_view;
overlay_frame last_overlay_frame;
uint32 last_horizontal_overlay_scale;
uint32 last_vertical_overlay_scale;
int device;
bool is_clone;
+102 -52
View File
@@ -29,15 +29,15 @@ set_color_key(overlay_registers *registers, uint8 red, uint8 green, uint8 blue,
registers->color_key_red = red;
registers->color_key_green = green;
registers->color_key_blue = blue;
registers->color_key_mask_red = redMask;
registers->color_key_mask_green = greenMask;
registers->color_key_mask_blue = blueMask;
registers->color_key_mask_red = ~redMask;
registers->color_key_mask_green = ~greenMask;
registers->color_key_mask_blue = ~blueMask;
registers->color_key_enabled = true;
}
static void
update_overlay(void)
update_overlay(bool updateCoefficients)
{
if (!gInfo->shared_info->overlay_active)
return;
@@ -48,7 +48,8 @@ update_overlay(void)
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
write_to_ring(ringBuffer, COMMAND_NOOP);
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_CONTINUE);
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers | 0x01);
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers
/* | (updateCoefficients ? OVERLAY_UPDATE_COEFFICIENTS : 0)*/);
ring_command_complete(ringBuffer);
TRACE(("update overlay: UPDATE: %lx, TEST: %lx, STATUS: %lx, EXTENDED_STATUS: %lx\n",
@@ -72,7 +73,8 @@ show_overlay(void)
write_to_ring(ringBuffer, COMMAND_FLUSH);
write_to_ring(ringBuffer, COMMAND_NOOP);
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_ON);
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers | 0x01);
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers
/*| OVERLAY_UPDATE_COEFFICIENTS*/);
ring_command_complete(ringBuffer);
}
@@ -88,8 +90,6 @@ hide_overlay(void)
gInfo->shared_info->overlay_active = false;
registers->overlay_enabled = false;
update_overlay();
ring_buffer &ringBuffer = gInfo->shared_info->primary_ring_buffer;
// flush pending commands
@@ -100,13 +100,13 @@ hide_overlay(void)
// clear overlay enabled bit
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_CONTINUE);
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers | 0x01);
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers);
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
write_to_ring(ringBuffer, COMMAND_NOOP);
// turn off overlay engine
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_OFF);
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers | 0x01);
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers);
write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP);
write_to_ring(ringBuffer, COMMAND_NOOP);
ring_command_complete(ringBuffer);
@@ -129,8 +129,10 @@ intel_overlay_count(const display_mode *mode)
const uint32 *
intel_overlay_supported_spaces(const display_mode *mode)
{
static const uint32 kSupportedSpaces[] = {/*B_RGB15, B_RGB16,*/ B_RGB32,
/*B_YCbCr411,*/ /*B_YCbCr422,*/ 0};
// Maybe I'm doing something wrong, but the chip is doing very strange
// stuff with anything but this color space (even though the docs/register
// definitions pretend to support other modes)
static const uint32 kSupportedSpaces[] = {B_YCbCr422, 0};
return kSupportedSpaces;
}
@@ -183,7 +185,7 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width,
buffer->space = colorSpace;
buffer->width = width;
buffer->height = height;
buffer->bytes_per_row = (width * bytesPerPixel + 0xf) & ~0xf;
buffer->bytes_per_row = (width * bytesPerPixel + 0x3f) & ~0x3f;
status_t status = intel_allocate_memory(buffer->bytes_per_row * height,
overlay->buffer_handle, overlay->buffer_offset);
@@ -210,7 +212,7 @@ intel_release_overlay_buffer(const overlay_buffer *buffer)
struct overlay *overlay = (struct overlay *)buffer;
// TODO: locking!
// TODO: if overlay is still active, hide it
if (gInfo->current_overlay == overlay)
hide_overlay();
@@ -273,11 +275,11 @@ intel_get_overlay_constraints(const display_mode *mode, const overlay_buffer *bu
constraints->window.height.min = 2;
constraints->window.height.max = mode->virtual_height;
// TODO: these values need to be checked
// TODO: the minimum values are not tested
constraints->h_scale.min = 1.0f / (1 << 4);
constraints->h_scale.max = 1 << 12;
constraints->h_scale.max = buffer->width * 7;
constraints->v_scale.min = 1.0f / (1 << 4);
constraints->v_scale.max = 1 << 12;
constraints->v_scale.max = buffer->height * 7;
return B_OK;
}
@@ -328,40 +330,53 @@ intel_configure_overlay(overlay_token overlayToken, const overlay_buffer *buffer
struct overlay *overlay = (struct overlay *)buffer;
overlay_registers *registers = gInfo->overlay_registers;
bool updateCoefficients = false;
switch (gInfo->shared_info->current_mode.space) {
case B_CMAP8:
set_color_key(registers, 0, 0, 0, 0xff, 0xff, 0xff);
break;
case B_RGB15:
set_color_key(registers, window->red.value, window->green.value,
window->blue.value, 0x07, 0x07, 0x07);
break;
case B_RGB16:
set_color_key(registers, window->red.value, window->green.value,
window->blue.value, 0x07, 0x03, 0x07);
break;
default:
set_color_key(registers, window->red.value, window->green.value,
window->blue.value, window->red.mask, window->green.mask, window->blue.mask);
break;
if (!gInfo->shared_info->overlay_active
|| memcmp(&gInfo->last_overlay_view, view, sizeof(overlay_view))
|| memcmp(&gInfo->last_overlay_frame, window, sizeof(overlay_frame))) {
// scaling has changed, program window and scaling factor
registers->window_left = window->h_start;
registers->window_top = window->v_start;
registers->window_width = window->width;
registers->window_height = window->height;
registers->source_width_rgb = view->width;
registers->source_width_uv = view->width;
registers->source_height_rgb = view->height;
registers->source_height_uv = view->height;
registers->source_bytes_per_row_rgb = (((overlay->buffer_offset + buffer->width + 0x1f) >> 5)
- (overlay->buffer_offset >> 5) - 1);
registers->source_bytes_per_row_uv = (((overlay->buffer_offset + buffer->width + 0x1f) >> 5)
- (overlay->buffer_offset >> 5) - 1);
uint32 horizontalScale = (view->width << 12) / window->width;
registers->scale_rgb.horizontal_downscale_factor = horizontalScale >> 12;
registers->scale_rgb.horizontal_scale_fraction = horizontalScale & 0xfff;
uint32 verticalScale = (view->height << 12) / window->height;
registers->scale_rgb.vertical_scale_fraction = verticalScale & 0xfff;
registers->vertical_scale_rgb = verticalScale >> 12;
registers->vertical_scale_uv = verticalScale >> 12;
TRACE(("scale: h = %ld.%ld, v = %ld.%ld\n", horizontalScale >> 12,
horizontalScale & 0xfff, verticalScale >> 12, verticalScale & 0xfff));
if (verticalScale != gInfo->last_vertical_overlay_scale
|| horizontalScale != gInfo->last_horizontal_overlay_scale) {
// TODO: recompute phase coefficients
updateCoefficients = true;
gInfo->last_vertical_overlay_scale = verticalScale;
gInfo->last_horizontal_overlay_scale = horizontalScale;
}
gInfo->last_overlay_view = *view;
gInfo->last_overlay_frame = *(overlay_frame *)window;
}
// program window and scaling factor
registers->window_left = 0;
registers->window_top = 0;
registers->window_width = view->width;//window->width;
registers->window_height = view->height;//window->height;
registers->source_width_rgb = buffer->width;
registers->source_width_uv = buffer->width;
registers->source_height_rgb = buffer->height;
registers->source_height_uv = buffer->height;
registers->source_bytes_per_row_rgb = buffer->bytes_per_row;
registers->source_bytes_per_row_uv = buffer->bytes_per_row;
registers->scale_rgb.horizontal_downscale_factor = 1;
registers->scale_uv.horizontal_downscale_factor = 1;
registers->color_control_output_mode = true;
registers->select_pipe = 0;
// program buffer
@@ -374,12 +389,47 @@ intel_configure_overlay(overlay_token overlayToken, const overlay_buffer *buffer
registers->stride_rgb = buffer->bytes_per_row;
registers->stride_uv = buffer->bytes_per_row;
registers->ycbcr422_order = 1;
switch (buffer->space) {
case B_RGB15:
registers->source_format = OVERLAY_FORMAT_RGB15;
break;
case B_RGB16:
registers->source_format = OVERLAY_FORMAT_RGB16;
break;
case B_RGB32:
registers->source_format = OVERLAY_FORMAT_RGB32;
break;
case B_YCbCr422:
registers->source_format = OVERLAY_FORMAT_YCbCr422;
break;
}
registers->ycbcr422_order = 0;
if (!gInfo->shared_info->overlay_active) {
// overlay is shown for the first time
switch (gInfo->shared_info->current_mode.space) {
case B_CMAP8:
set_color_key(registers, 0, 0, 0, 0xff, 0xff, 0xff);
break;
case B_RGB15:
set_color_key(registers, window->red.value, window->green.value,
window->blue.value, 0xf8, 0xf8, 0xf8);
break;
case B_RGB16:
set_color_key(registers, window->red.value, window->green.value,
window->blue.value, 0xf8, 0xfc, 0xf8);
break;
default:
set_color_key(registers, window->red.value, window->green.value,
window->blue.value, window->red.mask, window->green.mask, window->blue.mask);
break;
}
if (!gInfo->shared_info->overlay_active)
show_overlay();
else
update_overlay();
} else
update_overlay(updateCoefficients);
gInfo->current_overlay = overlay;
return B_OK;