BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / accelerants / radeon / overlay_management.c
blob4fdb41f45b2013f3ac0ed5d4c9db3cbdd1be8d75
1 /*
2 Copyright (c) 2002, Thomas Kurschel
5 Part of Radeon accelerant
7 Overlay interface
8 */
10 #include "GlobalData.h"
11 #include "radeon_interface.h"
12 #include "video_overlay.h"
13 #include <stdlib.h>
14 #include <sys/ioctl.h>
15 #include <string.h>
16 #include "overlay_regs.h"
17 #include "generic.h"
19 // we could add support of planar modes and YUV modes
20 // but I neither know how planar modes are defined nor
21 // whether there is any program that makes use of them
22 static uint32 overlay_colorspaces [] =
24 B_RGB15, B_RGB16, B_RGB32, B_YCbCr422, 0
28 // public function: number of overlay units
29 uint32 OVERLAY_COUNT( const display_mode *dm )
31 SHOW_FLOW0( 3, "" );
33 (void) dm;
35 return 1;
39 // public function: return list of supported overlay colour spaces
40 // dm - display mode where overlay is to be used
41 const uint32 *OVERLAY_SUPPORTED_SPACES( const display_mode *dm )
43 SHOW_FLOW0( 3, "" );
45 (void) dm;
47 return overlay_colorspaces;
51 // public function: returns supported features
52 // color_space - overlay's colour space
53 uint32 OVERLAY_SUPPORTED_FEATURES( uint32 color_space )
55 SHOW_FLOW0( 3, "" );
57 (void) color_space;
59 return
60 B_OVERLAY_COLOR_KEY |
61 B_OVERLAY_HORIZONTAL_FILTERING |
62 B_OVERLAY_VERTICAL_FILTERING;
66 // public function: allocates overlay buffer
67 // cs - overlay's colour space
68 // width, height - width and height of overlay buffer
69 const overlay_buffer *ALLOCATE_OVERLAY_BUFFER( color_space cs, uint16 width, uint16 height )
71 virtual_card *vc = ai->vc;
72 shared_info *si = ai->si;
73 radeon_alloc_mem am;
74 overlay_buffer_node *node;
75 overlay_buffer *buffer;
76 status_t result;
77 uint ati_space, test_reg, bpp;
79 SHOW_FLOW0( 3, "" );
81 switch( cs ) {
82 case B_RGB15:
83 SHOW_FLOW0( 3, "RGB15" );
84 bpp = 2;
85 ati_space = RADEON_SCALER_SOURCE_15BPP >> 8;
86 test_reg = 0;
87 break;
88 case B_RGB16:
89 SHOW_FLOW0( 3, "RGB16" );
90 bpp = 2;
91 ati_space = RADEON_SCALER_SOURCE_16BPP >> 8;
92 test_reg = 0;
93 break;
94 case B_RGB32:
95 SHOW_FLOW0( 3, "RGB32" );
96 bpp = 4;
97 ati_space = RADEON_SCALER_SOURCE_32BPP >> 8;
98 test_reg = 0;
99 break;
100 case B_YCbCr422:
101 SHOW_FLOW0( 3, "YCbCr422" );
102 bpp = 2;
103 // strange naming convention: VYUY has to be read backward,
104 // i.e. you get (low to high address) YUYV, which is what we want!
105 ati_space = RADEON_SCALER_SOURCE_VYUY422 >> 8;
106 test_reg = 0;
107 break;
108 // YUV12 is planar pixel format consisting of two or three planes
109 // I have no clue whether and how this format is used in BeOS
110 // (don't even know how it is defined officially)
111 /* case B_YUV12:
112 SHOW_FLOW0( 3, "YUV12" );
113 bpp = 2;
114 uvpp = 1;
115 ati_space = RADEON_SCALER_SOURCE_YUV12 >> 8;
116 testreg = 0;
117 break;*/
118 default:
119 SHOW_FLOW( 3, "Unsupported format (%x)", (int)cs );
120 return NULL;
123 node = malloc( sizeof( overlay_buffer_node ));
124 if( node == NULL )
125 return NULL;
127 node->ati_space = ati_space;
128 node->test_reg = test_reg;
130 ACQUIRE_BEN( si->engine.lock );
132 // alloc graphics mem
133 buffer = &node->buffer;
135 buffer->space = cs;
136 buffer->width = width;
137 buffer->height = height;
138 buffer->bytes_per_row = (width * bpp + 0xf) & ~0xf;
140 am.magic = RADEON_PRIVATE_DATA_MAGIC;
141 am.size = buffer->bytes_per_row * height;
142 am.memory_type = mt_local;
143 am.global = false;
145 result = ioctl( ai->fd, RADEON_ALLOC_MEM, &am );
146 if( result != B_OK )
147 goto err;
149 node->mem_handle = am.handle;
150 node->mem_offset = am.offset;
151 buffer->buffer = si->local_mem + am.offset;
152 buffer->buffer_dma = (void *) ((unsigned long) si->framebuffer_pci + am.offset);
154 // add to list of overlays
155 node->next = vc->overlay_buffers;
156 node->prev = NULL;
157 if( node->next )
158 node->next->prev = node;
160 vc->overlay_buffers = node;
162 RELEASE_BEN( si->engine.lock );
164 SHOW_FLOW( 0, "success: mem_handle=%x, offset=%x, CPU-address=%x, phys-address=%x",
165 node->mem_handle, node->mem_offset, buffer->buffer, buffer->buffer_dma );
167 return buffer;
169 err:
170 RELEASE_BEN( si->engine.lock );
171 return NULL;
175 // public function: discard overlay buffer
176 status_t RELEASE_OVERLAY_BUFFER( const overlay_buffer *ob )
178 virtual_card *vc = ai->vc;
179 shared_info *si = ai->si;
180 overlay_buffer_node *node;
181 radeon_free_mem fm;
182 status_t result;
184 SHOW_FLOW0( 3, "" );
186 node = (overlay_buffer_node *)((char *)ob - offsetof( overlay_buffer_node, buffer ));
188 if( si->active_overlay.on == node || si->active_overlay.prev_on )
189 Radeon_HideOverlay( ai );
191 // free memory
192 fm.magic = RADEON_PRIVATE_DATA_MAGIC;
193 fm.handle = node->mem_handle;
194 fm.memory_type = mt_local;
195 fm.global = false;
197 result = ioctl( ai->fd, RADEON_FREE_MEM, &fm );
198 if( result != B_OK ) {
199 SHOW_FLOW( 3, "ups - couldn't free memory (handle=%x, status=%s)",
200 node->mem_handle, strerror( result ));
203 ACQUIRE_BEN( si->engine.lock );
205 // remove from list
206 if( node->next )
207 node->next->prev = node->prev;
209 if( node->prev )
210 node->prev->next = node->next;
211 else
212 vc->overlay_buffers = node->next;
214 RELEASE_BEN( si->engine.lock );
216 SHOW_FLOW0( 3, "success" );
218 return B_OK;
222 // public function: get constraints of overlay unit
223 status_t GET_OVERLAY_CONSTRAINTS( const display_mode *dm, const overlay_buffer *ob,
224 overlay_constraints *oc )
226 SHOW_FLOW0( 3, "" );
228 // probably, this is paranoia as we only get called by app_server
229 // which should know what it's doing
230 if( dm == NULL || ob == NULL || oc == NULL )
231 return B_BAD_VALUE;
233 // scaler input restrictions
234 // TBD: check all these values; I reckon that
235 // most of them are too restrictive
237 // position
238 oc->view.h_alignment = 0;
239 oc->view.v_alignment = 0;
241 // alignment
242 switch (ob->space) {
243 case B_RGB15:
244 oc->view.width_alignment = 7;
245 break;
246 case B_RGB16:
247 oc->view.width_alignment = 7;
248 break;
249 case B_RGB32:
250 oc->view.width_alignment = 3;
251 break;
252 case B_YCbCr422:
253 oc->view.width_alignment = 7;
254 break;
255 case B_YUV12:
256 oc->view.width_alignment = 7;
257 default:
258 return B_BAD_VALUE;
260 oc->view.height_alignment = 0;
262 // size
263 oc->view.width.min = 4; // make 4-tap filter happy
264 oc->view.height.min = 4;
265 oc->view.width.max = ob->width;
266 oc->view.height.max = ob->height;
268 // scaler output restrictions
269 oc->window.h_alignment = 0;
270 oc->window.v_alignment = 0;
271 oc->window.width_alignment = 0;
272 oc->window.height_alignment = 0;
273 oc->window.width.min = 2;
274 oc->window.width.max = dm->virtual_width;
275 oc->window.height.min = 2;
276 oc->window.height.max = dm->virtual_height;
278 // TBD: these values need to be checked
279 // (shamelessly copied from Matrix driver)
280 oc->h_scale.min = 1.0f / (1 << 4);
281 oc->h_scale.max = 1 << 12;
282 oc->v_scale.min = 1.0f / (1 << 4);
283 oc->v_scale.max = 1 << 12;
285 SHOW_FLOW0( 3, "success" );
287 return B_OK;
291 // public function: allocate overlay unit
292 overlay_token ALLOCATE_OVERLAY( void )
294 shared_info *si = ai->si;
295 virtual_card *vc = ai->vc;
297 SHOW_FLOW0( 3, "" );
299 if( atomic_or( &si->overlay_mgr.inuse, 1 ) != 0 ) {
300 SHOW_FLOW0( 3, "already in use" );
301 return NULL;
304 SHOW_FLOW0( 3, "success" );
306 vc->uses_overlay = true;
308 return (void *)++si->overlay_mgr.token;
312 // public function: release overlay unit
313 status_t RELEASE_OVERLAY(overlay_token ot)
315 virtual_card *vc = ai->vc;
316 shared_info *si = ai->si;
318 SHOW_FLOW0( 3, "" );
320 if( (void *)si->overlay_mgr.token != ot )
321 return B_BAD_VALUE;
323 if( si->overlay_mgr.inuse == 0 )
324 return B_ERROR;
326 if( si->active_overlay.on )
327 Radeon_HideOverlay( ai );
329 si->overlay_mgr.inuse = 0;
330 vc->uses_overlay = false;
332 SHOW_FLOW0( 3, "released" );
334 return B_OK;
338 // public function: show/hide overlay
339 status_t CONFIGURE_OVERLAY( overlay_token ot, const overlay_buffer *ob,
340 const overlay_window *ow, const overlay_view *ov )
342 shared_info *si = ai->si;
343 status_t result;
345 SHOW_FLOW0( 4, "" );
347 if ( (uintptr_t)ot != si->overlay_mgr.token )
348 return B_BAD_VALUE;
350 if ( !si->overlay_mgr.inuse )
351 return B_BAD_VALUE;
353 if ( ow == NULL || ov == NULL ) {
354 SHOW_FLOW0( 3, "hide only" );
355 Radeon_HideOverlay( ai );
356 return B_OK;
359 if ( ob == NULL )
360 return B_ERROR;
362 ACQUIRE_BEN( si->engine.lock );
364 // store whished values
365 si->pending_overlay.ot = ot;
366 si->pending_overlay.ob = *ob;
367 si->pending_overlay.ow = *ow;
368 si->pending_overlay.ov = *ov;
370 si->pending_overlay.on = (overlay_buffer_node *)((char *)ob - offsetof( overlay_buffer_node, buffer ));
372 result = Radeon_UpdateOverlay( ai );
374 RELEASE_BEN( si->engine.lock );
376 return result;