* 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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user