📄 overlay_management.c
字号:
/* Copyright (c) 2002, Thomas Kurschel Part of Radeon accelerant Overlay interface*/#include "GlobalData.h"#include "radeon_interface.h"#include "video_overlay.h"#include <stdlib.h>#include <sys/ioctl.h>#include <string.h>#include "../regs/overlay_regs.h"// we could add support of planar modes and YUV modes// but I neither know how planar modes are defined nor// whether there is any program that makes use of themstatic uint32 overlay_colorspaces [] = { B_RGB15, B_RGB16, B_RGB32, B_YCbCr422, 0};// public function: number of overlay unitsuint32 OVERLAY_COUNT( const display_mode *dm ){ SHOW_FLOW0( 3, "" ); (void) dm; return 1;}// public function: return list of supported overlay colour spaces // dm - display mode where overlay is to be usedconst uint32 *OVERLAY_SUPPORTED_SPACES( const display_mode *dm ){ SHOW_FLOW0( 3, "" ); (void) dm; return overlay_colorspaces;}// public function: returns supported features // color_space - overlay's colour spaceuint32 OVERLAY_SUPPORTED_FEATURES( uint32 color_space ){ SHOW_FLOW0( 3, "" ); (void) color_space; return B_OVERLAY_COLOR_KEY | B_OVERLAY_HORIZONTAL_FILTERING | B_OVERLAY_VERTICAL_FILTERING;}// public function: allocates overlay buffer// cs - overlay's colour space// width, height - width and height of overlay bufferconst overlay_buffer *ALLOCATE_OVERLAY_BUFFER( color_space cs, uint16 width, uint16 height ){ virtual_card *vc = ai->vc; shared_info *si = ai->si; radeon_alloc_mem am; overlay_buffer_node *node; overlay_buffer *buffer; status_t result; uint ati_space, test_reg, bpp; SHOW_FLOW0( 3, "" ); switch( cs ) { case B_RGB15: SHOW_FLOW0( 3, "RGB15" ); bpp = 2; ati_space = RADEON_SCALER_SOURCE_15BPP >> 8; test_reg = 0; break; case B_RGB16: SHOW_FLOW0( 3, "RGB16" ); bpp = 2; ati_space = RADEON_SCALER_SOURCE_16BPP >> 8; test_reg = 0; break; case B_RGB32: SHOW_FLOW0( 3, "RGB32" ); bpp = 4; ati_space = RADEON_SCALER_SOURCE_32BPP >> 8; test_reg = 0; break; case B_YCbCr422: SHOW_FLOW0( 3, "YCbCr422" ); bpp = 2; // strange naming convention: VYUY has to be read backward, // i.e. you get (low to high address) YUYV, which is what we want! ati_space = RADEON_SCALER_SOURCE_VYUY422 >> 8; test_reg = 0; break; // YUV12 is planar pixel format consisting of two or three planes // I have no clue whether and how this format is used in BeOS // (don't even know how it is defined officially)/* case B_YUV12: SHOW_FLOW0( 3, "YUV12" ); bpp = 2; uvpp = 1; ati_space = RADEON_SCALER_SOURCE_YUV12 >> 8; testreg = 0; break;*/ default: SHOW_FLOW( 3, "Unsupported format (%x)", (int)cs ); return NULL; } node = malloc( sizeof( overlay_buffer_node )); if( node == NULL ) return NULL; node->ati_space = ati_space; node->test_reg = test_reg; ACQUIRE_BEN( si->engine.lock ); // alloc graphics mem buffer = &node->buffer; buffer->space = cs; buffer->width = width; buffer->height = height; buffer->bytes_per_row = (width * bpp + 0xf) & ~0xf; am.magic = RADEON_PRIVATE_DATA_MAGIC; am.size = buffer->bytes_per_row * height; am.memory_type = mt_local; am.global = false; result = ioctl( ai->fd, RADEON_ALLOC_MEM, &am ); if( result != B_OK ) goto err; node->mem_handle = am.handle; node->mem_offset = am.offset; buffer->buffer = si->local_mem + am.offset; buffer->buffer_dma = si->framebuffer_pci + am.offset; // add to list of overlays node->next = vc->overlay_buffers; node->prev = NULL; if( node->next ) node->next->prev = node; vc->overlay_buffers = node; RELEASE_BEN( si->engine.lock ); SHOW_FLOW( 0, "success: mem_handle=%x, offset=%x, CPU-address=%x, phys-address=%x", node->mem_handle, node->mem_offset, buffer->buffer, buffer->buffer_dma ); return buffer; err: RELEASE_BEN( si->engine.lock ); return NULL;}// public function: discard overlay bufferstatus_t RELEASE_OVERLAY_BUFFER( const overlay_buffer *ob ){ virtual_card *vc = ai->vc; shared_info *si = ai->si; overlay_buffer_node *node; radeon_free_mem fm; status_t result; SHOW_FLOW0( 3, "" ); node = (overlay_buffer_node *)((char *)ob - offsetof( overlay_buffer_node, buffer )); if( si->active_overlay.on == node || si->active_overlay.prev_on ) Radeon_HideOverlay( ai ); // free memory fm.magic = RADEON_PRIVATE_DATA_MAGIC; fm.handle = node->mem_handle; fm.memory_type = mt_local; fm.global = false; result = ioctl( ai->fd, RADEON_FREE_MEM, &fm ); if( result != B_OK ) { SHOW_FLOW( 3, "ups - couldn't free memory (handle=%x, status=%s)", node->mem_handle, strerror( result )); } ACQUIRE_BEN( si->engine.lock ); // remove from list if( node->next ) node->next->prev = node->prev; if( node->prev ) node->prev->next = node->next; else vc->overlay_buffers = node->next; RELEASE_BEN( si->engine.lock ); SHOW_FLOW0( 3, "success" ); return B_OK;}// public function: get constraints of overlay unitstatus_t GET_OVERLAY_CONSTRAINTS( const display_mode *dm, const overlay_buffer *ob, overlay_constraints *oc ){ SHOW_FLOW0( 3, "" ); // probably, this is paranoia as we only get called by app_server // which should know what it's doing if( dm == NULL || ob == NULL || oc == NULL ) return B_BAD_VALUE; // scaler input restrictions // TBD: check all these values; I reckon that // most of them are too restrictive // position oc->view.h_alignment = 0; oc->view.v_alignment = 0; // alignment switch (ob->space) { case B_RGB15: oc->view.width_alignment = 7; break; case B_RGB16: oc->view.width_alignment = 7; break; case B_RGB32: oc->view.width_alignment = 3; break; case B_YCbCr422: oc->view.width_alignment = 7; break; case B_YUV12: oc->view.width_alignment = 7; default: return B_BAD_VALUE; } oc->view.height_alignment = 0; // size oc->view.width.min = 4; // make 4-tap filter happy oc->view.height.min = 4; oc->view.width.max = ob->width; oc->view.height.max = ob->height; // scaler output restrictions oc->window.h_alignment = 0; oc->window.v_alignment = 0; oc->window.width_alignment = 0; oc->window.height_alignment = 0; oc->window.width.min = 2; oc->window.width.max = dm->virtual_width; oc->window.height.min = 2; oc->window.height.max = dm->virtual_height; // TBD: these values need to be checked // (shamelessly copied from Matrix driver) oc->h_scale.min = 1.0f / (1 << 4); oc->h_scale.max = 1 << 12; oc->v_scale.min = 1.0f / (1 << 4); oc->v_scale.max = 1 << 12; SHOW_FLOW0( 3, "success" ); return B_OK;}// public function: allocate overlay unitoverlay_token ALLOCATE_OVERLAY( void ){ shared_info *si = ai->si; virtual_card *vc = ai->vc; SHOW_FLOW0( 3, "" ); if( atomic_or( &si->overlay_mgr.inuse, 1 ) != 0 ) { SHOW_FLOW0( 3, "already in use" ); return NULL; } SHOW_FLOW0( 3, "success" ); vc->uses_overlay = true; return (void *)++si->overlay_mgr.token;}// public function: release overlay unitstatus_t RELEASE_OVERLAY(overlay_token ot){ virtual_card *vc = ai->vc; shared_info *si = ai->si; SHOW_FLOW0( 3, "" ); if( (void *)si->overlay_mgr.token != ot ) return B_BAD_VALUE; if( si->overlay_mgr.inuse == 0 ) return B_ERROR; if( si->active_overlay.on ) Radeon_HideOverlay( ai ); si->overlay_mgr.inuse = 0; vc->uses_overlay = false; SHOW_FLOW0( 3, "released" ); return B_OK;}// public function: show/hide overlaystatus_t CONFIGURE_OVERLAY( overlay_token ot, const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov ){ shared_info *si = ai->si; status_t result; SHOW_FLOW0( 4, "" ); if( (uint32)ot != si->overlay_mgr.token ) return B_BAD_VALUE; if( !si->overlay_mgr.inuse ) return B_BAD_VALUE; if( ow == NULL || ov == NULL ) { SHOW_FLOW0( 3, "hide only" ); Radeon_HideOverlay( ai ); return B_OK; } if( ob == NULL ) return B_ERROR; ACQUIRE_BEN( si->engine.lock ); // store whished values si->pending_overlay.ot = ot; si->pending_overlay.ob = *ob; si->pending_overlay.ow = *ow; si->pending_overlay.ov = *ov; si->pending_overlay.on = (overlay_buffer_node *)((char *)ob - offsetof( overlay_buffer_node, buffer )); result = Radeon_UpdateOverlay( ai ); RELEASE_BEN( si->engine.lock ); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -