diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index ef7ef40e98..d7c34101ed 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -72,6 +72,7 @@ struct intel_shared_info { ring_buffer primary_ring_buffer; int32 overlay_channel_used; + bool overlay_active; uint32 overlay_token; uint8* physical_overlay_registers; @@ -256,13 +257,13 @@ struct overlay_registers { uint16 vertical_phase1_uv; uint16 horizontal_phase_rgb; uint16 horizontal_phase_uv; - uint32 _reserved0 : 8; uint32 initial_vertical_phase0_shift_rgb0 : 4; uint32 initial_vertical_phase1_shift_rgb0 : 4; uint32 initial_horizontal_phase_shift_rgb0 : 4; uint32 initial_vertical_phase0_shift_uv : 4; uint32 initial_vertical_phase1_shift_uv : 4; uint32 initial_horizontal_phase_shift_uv : 4; + uint32 _reserved0 : 8; uint16 window_left; uint16 window_top; uint16 window_width; @@ -276,66 +277,66 @@ struct overlay_registers { overlay_scale scale_rgb; overlay_scale scale_uv; // (0x48) OCLRC0 - overlay color correction 0 - uint32 _reserved1 : 5; - uint32 contrast_correction : 9; // fixed point: 3.6 bits - uint32 _reserved2 : 10; uint32 brightness_correction : 8; // signed, -128 to 127 + uint32 _reserved1 : 10; + uint32 contrast_correction : 9; // fixed point: 3.6 bits + uint32 _reserved2 : 5; // (0x4c) OCLRC1 - overlay color correction 1 - uint32 _reserved3 : 5; - uint32 saturation_sin_correction : 11; // signed fixed point: 3.7 bits - uint32 _reserved4 : 6; uint32 saturation_cos_correction : 10; // fixed point: 3.7 bits + uint32 _reserved3 : 6; + uint32 saturation_sin_correction : 11; // signed fixed point: 3.7 bits + uint32 _reserved4 : 5; // (0x50) DCLRKV - destination color key value - uint32 _reserved5 : 8; - uint32 color_key_red : 8; - uint32 color_key_green : 8; uint32 color_key_blue : 8; + uint32 color_key_green : 8; + uint32 color_key_red : 8; + uint32 _reserved5 : 8; // (0x54) DCLRKM - destination color key mask - uint32 color_key_enabled : 1; - uint32 _reserved6 : 7; - uint32 color_key_mask_red : 8; - uint32 color_key_mask_green : 8; uint32 color_key_mask_blue : 8; + uint32 color_key_mask_green : 8; + uint32 color_key_mask_red : 8; + uint32 _reserved6 : 7; + uint32 color_key_enabled : 1; // (0x58) SCHRKVH - source chroma key high value - uint32 _reserved7 : 8; - uint32 source_chroma_key_high_green : 8; - uint32 source_chroma_key_high_blue : 8; uint32 source_chroma_key_high_red : 8; + uint32 source_chroma_key_high_blue : 8; + uint32 source_chroma_key_high_green : 8; + uint32 _reserved7 : 8; // (0x5c) SCHRKVL - source chroma key low value - uint32 _reserved8 : 8; - uint32 source_chroma_key_low_green : 8; - uint32 source_chroma_key_low_blue : 8; uint32 source_chroma_key_low_red : 8; + uint32 source_chroma_key_low_blue : 8; + uint32 source_chroma_key_low_green : 8; + uint32 _reserved8 : 8; // (0x60) SCHRKEN - source chroma key enable - uint32 _reserved9 : 5; - uint32 source_chroma_key_green_enabled : 1; - uint32 source_chroma_key_blue_enabled : 1; + uint32 _reserved9 : 24; uint32 source_chroma_key_red_enabled : 1; - uint32 _reserved10 : 24; + uint32 source_chroma_key_blue_enabled : 1; + uint32 source_chroma_key_green_enabled : 1; + uint32 _reserved10 : 5; // (0x64) OCONFIG - overlay configuration - uint32 _reserved11 : 5; - uint32 slot_time : 8; - uint32 _reserved12 : 2; - uint32 gamma2_enabled : 1; - uint32 _reserved13 : 11; - uint32 yuv_to_rgb_bypass : 1; + uint32 _reserved11 : 3; uint32 color_control_output_mode : 1; - uint32 _reserved14 : 3; + uint32 yuv_to_rgb_bypass : 1; + uint32 _reserved12 : 11; + uint32 gamma2_enabled : 1; + uint32 _reserved13 : 2; + uint32 slot_time : 8; + uint32 _reserved14 : 5; // (0x68) OCOMD - overlay command - uint32 _reserved15 : 13; - uint32 mirroring_mode : 2; - uint32 _reserved16 : 1; - uint32 ycbcr422_order : 2; - uint32 _reserved17 : 4; - uint32 tv_flip_field_parity : 1; - uint32 _reserved18 : 1; - uint32 tv_flip_field_enabled : 1; - uint32 _reserved19 : 1; - uint32 buffer_field_mode : 1; - uint32 test_mode : 1; - uint32 active_buffer : 2; - uint32 active_field : 1; uint32 overlay_enabled : 1; + uint32 active_field : 1; + uint32 active_buffer : 2; + uint32 test_mode : 1; + uint32 buffer_field_mode : 1; + uint32 _reserved15 : 1; + uint32 tv_flip_field_enabled : 1; + uint32 _reserved16 : 1; + uint32 tv_flip_field_parity : 1; + uint32 _reserved17 : 4; + uint32 ycbcr422_order : 2; + uint32 _reserved18 : 1; + uint32 mirroring_mode : 2; + uint32 _reserved19 : 13; uint32 _reserved20; @@ -349,6 +350,7 @@ struct overlay_registers { // (0xa0) FASTHSCALE - fast horizontal downscale uint16 horizontal_scale_rgb; uint16 horizontal_scale_uv; + // (0xa4) UVSCALEV - vertical downscale uint16 vertical_scale_rgb; uint16 vertical_scale_uv; }; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index ef2a43b04c..01ed07b8a5 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -10,6 +10,8 @@ #include "accelerant_protos.h" #include "accelerant.h" +#include "utility.h" + #include #include #include @@ -129,6 +131,9 @@ init_common(int device, bool isClone) sharedCloner.Keep(); regsCloner.Keep(); + gInfo->overlay_registers = (struct overlay_registers *)((uint8 *)gInfo->shared_info + + ROUND_TO_PAGE_SIZE(sizeof(intel_shared_info))); + return B_OK; } diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index 16d2c12184..328af8cff3 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -32,6 +32,9 @@ struct accelerant_info { uint32 frame_buffer_handle; + struct overlay_registers *overlay_registers; + overlay *current_overlay; + int device; bool is_clone; }; @@ -59,6 +62,8 @@ extern void set_display_power_mode(uint32 mode); // engine.cpp extern void setup_ring_buffer(ring_buffer &ringBuffer, const char *name); +extern void write_to_ring(ring_buffer &ring, uint32 value); +extern void ring_command_complete(ring_buffer &ring); // modes.cpp extern status_t create_mode_list(void); diff --git a/src/add-ons/accelerants/intel_extreme/engine.cpp b/src/add-ons/accelerants/intel_extreme/engine.cpp index e99a6607ce..6fd9bac195 100644 --- a/src/add-ons/accelerants/intel_extreme/engine.cpp +++ b/src/add-ons/accelerants/intel_extreme/engine.cpp @@ -25,7 +25,7 @@ static engine_token sEngineToken = {1, 0 /*B_2D_ACCELERATION*/, NULL}; /** The ring buffer must be locked when calling this function */ -static inline void +void write_to_ring(ring_buffer &ring, uint32 value) { uint32 *target = (uint32 *)(ring.base + ring.position); @@ -37,7 +37,7 @@ write_to_ring(ring_buffer &ring, uint32 value) /** The ring buffer must be locked when calling this function */ -static inline void +void ring_command_complete(ring_buffer &ring) { if (ring.position & 0x07) { @@ -46,6 +46,11 @@ ring_command_complete(ring_buffer &ring) } write32(ring.register_base + RING_BUFFER_TAIL, ring.position); + + // make sure memory is written back in case the ring buffer + // is in write combining mode + int32 test; + atomic_add(&test, 1); } diff --git a/src/add-ons/accelerants/intel_extreme/overlay.cpp b/src/add-ons/accelerants/intel_extreme/overlay.cpp index 6ab6ada4e3..1906593340 100644 --- a/src/add-ons/accelerants/intel_extreme/overlay.cpp +++ b/src/add-ons/accelerants/intel_extreme/overlay.cpp @@ -22,9 +22,96 @@ extern "C" void _sPrintf(const char *format, ...); #endif +static void +set_color_key(overlay_registers *registers, uint8 red, uint8 green, uint8 blue, + uint8 redMask, uint8 greenMask, uint8 blueMask) +{ + 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_enabled = true; +} + + +static void +update_overlay(void) +{ + if (!gInfo->shared_info->overlay_active) + return; + + ring_buffer &ringBuffer = gInfo->shared_info->primary_ring_buffer; + write_to_ring(ringBuffer, COMMAND_FLUSH); + write_to_ring(ringBuffer, COMMAND_NOOP); + 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); + ring_command_complete(ringBuffer); + + TRACE(("update overlay: UPDATE: %lx, TEST: %lx, STATUS: %lx, EXTENDED_STATUS: %lx\n", + read32(INTEL_OVERLAY_UPDATE), read32(INTEL_OVERLAY_TEST), read32(INTEL_OVERLAY_STATUS), + read32(INTEL_OVERLAY_EXTENDED_STATUS))); +} + + +static void +show_overlay(void) +{ + if (gInfo->shared_info->overlay_active) + return; + + overlay_registers *registers = gInfo->overlay_registers; + + gInfo->shared_info->overlay_active = true; + registers->overlay_enabled = true; + + ring_buffer &ringBuffer = gInfo->shared_info->primary_ring_buffer; + 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); + ring_command_complete(ringBuffer); +} + + static void hide_overlay(void) { + if (!gInfo->shared_info->overlay_active) + return; + + overlay_registers *registers = gInfo->overlay_registers; + + gInfo->shared_info->overlay_active = false; + registers->overlay_enabled = false; + + update_overlay(); + + ring_buffer &ringBuffer = gInfo->shared_info->primary_ring_buffer; + + // flush pending commands + write_to_ring(ringBuffer, COMMAND_FLUSH); + write_to_ring(ringBuffer, COMMAND_NOOP); + write_to_ring(ringBuffer, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP); + write_to_ring(ringBuffer, COMMAND_NOOP); + + // 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, 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, COMMAND_WAIT_FOR_EVENT | COMMAND_WAIT_FOR_OVERLAY_FLIP); + write_to_ring(ringBuffer, COMMAND_NOOP); + ring_command_complete(ringBuffer); + + gInfo->current_overlay = NULL; } @@ -42,8 +129,8 @@ 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}; + static const uint32 kSupportedSpaces[] = {/*B_RGB15, B_RGB16,*/ B_RGB32, + /*B_YCbCr411,*/ /*B_YCbCr422,*/ 0}; return kSupportedSpaces; } @@ -62,6 +149,9 @@ const overlay_buffer * intel_allocate_overlay_buffer(color_space colorSpace, uint16 width, uint16 height) { + TRACE(("intel_allocate_overlay_buffer(width %u, height %u, colorSpace %lu)\n", + width, height, colorSpace)); + uint32 bytesPerPixel; switch (colorSpace) { @@ -105,7 +195,7 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width, buffer->buffer = gInfo->shared_info->graphics_memory + overlay->buffer_offset; buffer->buffer_dma = gInfo->shared_info->physical_graphics_memory + overlay->buffer_offset; - TRACE(("allocated overlay buffer: handle=%x, offset=%x, address=%x, phys-address=%x", + TRACE(("allocated overlay buffer: handle=%x, offset=%x, address=%x, physical address=%x\n", overlay->buffer_handle, overlay->buffer_offset, buffer->buffer, buffer->buffer_dma)); return buffer; @@ -115,10 +205,14 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width, status_t intel_release_overlay_buffer(const overlay_buffer *buffer) { + TRACE(("intel_release_overlay_buffer(buffer %p)\n", buffer)); + struct overlay *overlay = (struct overlay *)buffer; // TODO: locking! // TODO: if overlay is still active, hide it + if (gInfo->current_overlay == overlay) + hide_overlay(); intel_free_memory(overlay->buffer_handle); free(overlay); @@ -131,6 +225,8 @@ status_t intel_get_overlay_constraints(const display_mode *mode, const overlay_buffer *buffer, overlay_constraints *constraints) { + TRACE(("intel_get_overlay_constraints(buffer %p)\n", buffer)); + // taken from the Radeon driver... // scaler input restrictions @@ -190,6 +286,8 @@ intel_get_overlay_constraints(const display_mode *mode, const overlay_buffer *bu overlay_token intel_allocate_overlay(void) { + TRACE(("intel_allocate_overlay()\n")); + // we only have a single overlay channel if (atomic_or(&gInfo->shared_info->overlay_channel_used, 1) != 0) return NULL; @@ -201,11 +299,14 @@ intel_allocate_overlay(void) status_t intel_release_overlay(overlay_token overlayToken) { + TRACE(("intel_allocate_overlay(token %ld)\n", (uint32)overlayToken)); + // we only have a single token, which simplifies this if (overlayToken != (overlay_token)gInfo->shared_info->overlay_token) return B_BAD_VALUE; atomic_and(&gInfo->shared_info->overlay_channel_used, 0); + return B_OK; } @@ -214,6 +315,9 @@ status_t intel_configure_overlay(overlay_token overlayToken, const overlay_buffer *buffer, const overlay_window *window, const overlay_view *view) { + TRACE(("intel_configure_overlay: buffer %p, window %p, view %p\n", + buffer, window, view)); + if (overlayToken != (overlay_token)gInfo->shared_info->overlay_token) return B_BAD_VALUE; @@ -222,7 +326,62 @@ intel_configure_overlay(overlay_token overlayToken, const overlay_buffer *buffer return B_OK; } + struct overlay *overlay = (struct overlay *)buffer; + overlay_registers *registers = gInfo->overlay_registers; + + 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; + } + + // 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; + + // program buffer + + registers->buffer_rgb0 = overlay->buffer_offset; + registers->buffer_rgb1 = overlay->buffer_offset; + registers->buffer_u0 = overlay->buffer_offset; + registers->buffer_u1 = overlay->buffer_offset; + registers->buffer_v0 = overlay->buffer_offset; + registers->buffer_v1 = overlay->buffer_offset; + registers->stride_rgb = buffer->bytes_per_row; + registers->stride_uv = buffer->bytes_per_row; + + registers->ycbcr422_order = 1; + + if (!gInfo->shared_info->overlay_active) + show_overlay(); + else + update_overlay(); + + gInfo->current_overlay = overlay; return B_OK; }