1 /* Written by Rudolf Cornelissen 05/2002-4/2006 */
3 /* Note on 'missing features' in BeOS 5.0.3 and DANO:
4 * BeOS needs to define more colorspaces! It would be nice if BeOS would support the FourCC 'definitions'
5 * of colorspaces. These colorspaces are 32bit words, so it could be simply done (or is it already so?)
8 #define MODULE_BIT 0x00000400
12 /* define the supported overlay input colorspaces */
13 /* It would be nice to have the YUV4:2:0 2-plane mode implemented also later on, but the Be colorspace
14 * definitions (in GraphicsDefs.h, R5.0.3 and DANO5.1d0) do not include this one... */
15 static uint32 overlay_colorspaces
[] = { (uint32
)B_YCbCr422
, (uint32
)B_NO_COLOR_SPACE
};
17 uint32
OVERLAY_COUNT(const display_mode
*dm
)
18 // This method is never used AFAIK though it *is* exported on R5.0.3 and DANO.
19 // Does someone know howto invoke it?
21 LOG(4,("Overlay: count called\n"));
23 /* check for NULL pointer */
26 LOG(4,("Overlay: No display mode specified!\n"));
28 /* apparantly overlay count should report the number of 'overlay units' on the card */
32 const uint32
*OVERLAY_SUPPORTED_SPACES(const display_mode
*dm
)
33 // This method is never used AFAIK though it *is* exported on R5.0.3 and DANO.
34 // Does someone know howto invoke it?
36 LOG(4,("Overlay: supported_spaces called.\n"));
38 /* check for NULL pointer */
41 LOG(4,("Overlay: No display mode specified!\n"));
45 /* assuming interlaced VGA is not supported */
46 if (dm
->timing
.flags
& B_TIMING_INTERLACED
)
50 /* return a B_NO_COLOR_SPACE terminated list */
51 return &overlay_colorspaces
[0];
54 uint32
OVERLAY_SUPPORTED_FEATURES(uint32 a_color_space
)
55 // This method is never used AFAIK. On R5.0.3 and DANO it is not even exported!
57 LOG(4,("Overlay: supported_features: color_space $%08x\n",a_color_space
));
59 /* check what features are supported for the current overlaybitmap colorspace */
60 switch (a_color_space
)
64 ( B_OVERLAY_COLOR_KEY
|
65 B_OVERLAY_HORIZONTAL_FILTERING
|
66 B_OVERLAY_VERTICAL_FILTERING
);
70 const overlay_buffer
*ALLOCATE_OVERLAY_BUFFER(color_space cs
, uint16 width
, uint16 height
)
72 int offset
= 0; /* used to determine next buffer to create */
73 uintptr_t adress
, adress2
, temp32
; /* used to calculate buffer adresses */
74 uint32 oldsize
= 0; /* used to 'squeeze' new buffers between already existing ones */
75 int cnt
; /* loopcounter */
77 /* acquire the shared benaphore */
78 AQUIRE_BEN(si
->overlay
.lock
)
80 LOG(4,("Overlay: cardRAM_start = $%p\n", (uint8
*)si
->framebuffer
));
81 LOG(4,("Overlay: cardRAM_start_DMA = $%p\n", (uint8
*)si
->framebuffer_pci
));
82 LOG(4,("Overlay: cardRAM_size = %3.3fMb\n",(si
->ps
.memory_size
/ (1024.0 * 1024.0))));
84 /* find first empty slot (room for another buffer?) */
85 for (offset
= 0; offset
< MAXBUFFERS
; offset
++)
87 if (si
->overlay
.myBuffer
[offset
].buffer
== NULL
) break;
90 LOG(4,("Overlay: Allocate_buffer offset = %d\n",offset
));
92 if (offset
< MAXBUFFERS
)
93 /* setup new scaler input buffer */
98 /* check if slopspace is needed: VIA CLE266 needs ~0x0007. */
99 si
->overlay
.myBuffer
[offset
].width
= ((width
+ 0x0007) & ~0x0007);
100 si
->overlay
.myBuffer
[offset
].bytes_per_row
= 2 * si
->overlay
.myBuffer
[offset
].width
;
102 /* check if the requested horizontal pitch is supported: */
103 //fixme: tune for VIA... (overruled below, this should probably be a bytes_per_row check)
104 if (si
->overlay
.myBuffer
[offset
].width
> 4088)
106 LOG(4,("Overlay: Sorry, requested buffer pitch not supported, aborted\n"));
108 /* release the shared benaphore */
109 RELEASE_BEN(si
->overlay
.lock
)
115 /* unsupported colorspace! */
116 LOG(4,("Overlay: Sorry, colorspace $%08x not supported, aborted\n",cs
));
118 /* release the shared benaphore */
119 RELEASE_BEN(si
->overlay
.lock
)
125 /* check if the requested buffer width is supported */
126 if (si
->overlay
.myBuffer
[offset
].width
> 1024)
128 LOG(4,("Overlay: Sorry, requested buffer width not supported, aborted\n"));
130 /* release the shared benaphore */
131 RELEASE_BEN(si
->overlay
.lock
)
135 /* check if the requested buffer height is supported */
138 LOG(4,("Overlay: Sorry, requested buffer height not supported, aborted\n"));
140 /* release the shared benaphore */
141 RELEASE_BEN(si
->overlay
.lock
)
146 /* store slopspace (in pixels) for each bitmap for use by 'overlay unit' (BES) */
147 si
->overlay
.myBufInfo
[offset
].slopspace
= si
->overlay
.myBuffer
[offset
].width
- width
;
149 si
->overlay
.myBuffer
[offset
].space
= cs
;
150 si
->overlay
.myBuffer
[offset
].height
= height
;
152 /* we define the overlay buffers to reside 'in the back' of the cards RAM */
153 /* NOTE to app programmers:
154 * Beware that an app using overlay needs to track workspace switches and screenprefs
155 * changes. If such an action is detected, the app needs to reset it's pointers to the
156 * newly created overlay bitmaps, which will be assigned by BeOS automatically after such
157 * an event. (Also the app needs to respect the new overlay_constraints that will be applicable!)
159 * It is entirely possible that new bitmaps may *not* be re-setup at all, or less of them
160 * than previously setup by the app might be re-setup. This is due to cardRAM restraints then.
161 * This means that the app should also check for NULL pointers returned by the bitmaps,
162 * and if this happens, it needs to fallback to single buffered overlay or even fallback to
163 * bitmap output for the new situation. */
165 /* Another NOTE for app programmers:
166 * A *positive* side-effect of assigning the first overlay buffer exactly at the end of the
167 * cardRAM is that apps that try to write beyond the buffer's space get a segfault immediately.
168 * This *greatly* simplifies tracking such errors!
169 * Of course such errors may lead to strange effects in the app or driver behaviour if they are
170 * not hunted down and removed.. */
172 /* calculate first free RAM adress in card:
173 * Driver setup is as follows:
174 * card base: - hardware cursor bitmap (if used),
175 * directly above - screen memory for both heads */
176 adress2
= (((uintptr_t)((uint8
*)si
->fbc
.frame_buffer
)) + /* cursor already included here */
177 (si
->fbc
.bytes_per_row
* si
->dm
.virtual_height
)); /* size in bytes of screen(s) */
178 LOG(4,("Overlay: first free cardRAM virtual adress $%08x\n", adress2
));
180 /* calculate 'preliminary' buffer size including slopspace */
181 oldsize
= si
->overlay
.myBufInfo
[offset
].size
;
182 si
->overlay
.myBufInfo
[offset
].size
=
183 si
->overlay
.myBuffer
[offset
].bytes_per_row
* si
->overlay
.myBuffer
[offset
].height
;
185 /* calculate virtual memory adress that would be needed for a new bitmap */
186 /* NOTE to app programmers:
187 * For testing app behaviour regarding workspace switches or screen prefs changes to settings
188 * that do not have enough cardRAM left for allocation of overlay bitmaps, you need a card with
189 * a low amount of RAM. Or you can set in the file skel.settings for example:
190 * memory 8 #8Mb RAM on card
191 * and reboot (this simulates 8Mb RAM on the card).
193 * If you switch now to settings: 1600x1200x32bit (single head) the app needs to fallback to
194 * bitmap output or maybe single buffered overlay output if small bitmaps are used. */
196 adress
= (((uintptr_t)((uint8
*)si
->framebuffer
)) + si
->ps
.memory_size
);
197 for (cnt
= 0; cnt
<= offset
; cnt
++)
199 adress
-= si
->overlay
.myBufInfo
[cnt
].size
;
202 /* the > G200 scalers require buffers to be aligned to 16 byte pages cardRAM offset, G200 can do with
203 * 8 byte pages cardRAM offset. Compatible settings used, has no real downside consequences here */
205 /* Check if we need to modify the buffers starting adress and thus the size */
206 /* calculate 'would be' cardRAM offset */
207 temp32
= (adress
- ((uintptr_t)((vuint32
*)si
->framebuffer
)));
208 /* check if it is aligned */
209 if (temp32
!= (temp32
& 0xfffffff0))
211 /* update the (already calculated) buffersize to get it aligned */
212 si
->overlay
.myBufInfo
[offset
].size
+= (temp32
- (temp32
& 0xfffffff0));
213 /* update the (already calculated) adress to get it aligned */
214 adress
-= (temp32
- (temp32
& 0xfffffff0));
216 LOG(4,("Overlay: new buffer needs virtual adress $%08x\n", adress
));
218 /* First check now if buffer to be defined is 'last one' in memory (speaking backwards):
219 * this is done to prevent a large buffer getting created in the space a small buffer
220 * occupied earlier, if not all buffers created were deleted.
221 * Note also that the app can delete the buffers in any order desired. */
223 /* NOTE to app programmers:
224 * If you are going to delete a overlay buffer you created, you should delete them *all* and
225 * then re-create only the new ones needed. This way you are sure not to get unused memory-
226 * space in between your overlay buffers for instance, so cardRAM is used 'to the max'.
227 * If you don't, you might not get a buffer at all if you are trying to set up a larger one
229 * (Indeed: not all buffers *have* to be of the same type and size...) */
231 for (cnt
= offset
; cnt
< MAXBUFFERS
; cnt
++)
233 if (si
->overlay
.myBuffer
[cnt
].buffer
!= NULL
)
235 /* Check if the new buffer would fit into the space the single old one used here */
236 if (si
->overlay
.myBufInfo
[offset
].size
<= oldsize
)
238 /* It does, so we reset to the old size and adresses to prevent the space from shrinking
239 * if we get here again... */
240 adress
-= (oldsize
- si
->overlay
.myBufInfo
[offset
].size
);
241 si
->overlay
.myBufInfo
[offset
].size
= oldsize
;
242 LOG(4,("Overlay: 'squeezing' in buffer:\n"
243 "Overlay: resetting it to virtual adress $%08x and size $%08x\n", adress
,oldsize
));
244 /* force exiting the FOR loop */
250 LOG(4,("Overlay: Other buffer(s) exist after this one:\n"
251 "Overlay: not enough space to 'squeeze' this one in, aborted\n"));
253 /* Reset to the old size to prevent the space from 'growing' if we get here again... */
254 si
->overlay
.myBufInfo
[offset
].size
= oldsize
;
256 /* release the shared benaphore */
257 RELEASE_BEN(si
->overlay
.lock
)
264 /* check if we have enough space to setup this new bitmap
265 * (preventing overlap of desktop RAMspace & overlay bitmap RAMspace here) */
266 if (adress
< adress2
)
269 LOG(4,("Overlay: Sorry, no more space for buffers: aborted\n"));
271 /* release the shared benaphore */
272 RELEASE_BEN(si
->overlay
.lock
)
276 /* continue buffer setup */
277 si
->overlay
.myBuffer
[offset
].buffer
= (void *) adress
;
279 /* calculate physical memory adress (for dma use) */
280 adress
= (((uintptr_t)((uint8
*)si
->framebuffer_pci
)) + si
->ps
.memory_size
);
281 for (cnt
= 0; cnt
<= offset
; cnt
++)
283 adress
-= si
->overlay
.myBufInfo
[cnt
].size
;
285 /* this adress is already aligned to the scaler's requirements (via the already modified sizes) */
286 si
->overlay
.myBuffer
[offset
].buffer_dma
= (void *) adress
;
288 LOG(4,("Overlay: New buffer: addr $%p, dma_addr $%p, color space $%p\n",
289 (uint8
*)si
->overlay
.myBuffer
[offset
].buffer
,
290 (uint8
*)si
->overlay
.myBuffer
[offset
].buffer_dma
, cs
));
291 LOG(4,("Overlay: New buffer's size is $%08x\n", si
->overlay
.myBufInfo
[offset
].size
));
293 /* release the shared benaphore */
294 RELEASE_BEN(si
->overlay
.lock
)
296 return &si
->overlay
.myBuffer
[offset
];
299 /* sorry, no more room for buffers */
301 LOG(4,("Overlay: Sorry, no more space for buffers: aborted\n"));
303 /* release the shared benaphore */
304 RELEASE_BEN(si
->overlay
.lock
)
310 status_t
RELEASE_OVERLAY_BUFFER(const overlay_buffer
*ob
)
311 /* Note that the user can delete the buffers in any order desired! */
317 /* find the buffer */
318 for (offset
= 0; offset
< MAXBUFFERS
; offset
++)
320 if (si
->overlay
.myBuffer
[offset
].buffer
== ob
->buffer
) break;
323 if (offset
< MAXBUFFERS
)
324 /* delete current buffer */
326 si
->overlay
.myBuffer
[offset
].buffer
= NULL
;
327 si
->overlay
.myBuffer
[offset
].buffer_dma
= NULL
;
329 LOG(4,("Overlay: Release_buffer offset = %d, buffer released\n",offset
));
335 /* this is no buffer of ours! */
336 LOG(4,("Overlay: Release_overlay_buffer: not ours, aborted!\n"));
342 /* no buffer specified! */
344 LOG(4,("Overlay: Release_overlay_buffer: no buffer specified, aborted!\n"));
350 status_t GET_OVERLAY_CONSTRAINTS
351 (const display_mode
*dm
, const overlay_buffer
*ob
, overlay_constraints
*oc
)
355 LOG(4,("Overlay: Get_overlay_constraints called\n"));
357 /* check for NULL pointers */
358 if ((dm
== NULL
) || (ob
== NULL
) || (oc
== NULL
))
360 LOG(4,("Overlay: Get_overlay_constraints: Null pointer(s) detected!\n"));
364 /* find the buffer */
365 for (offset
= 0; offset
< MAXBUFFERS
; offset
++)
367 if (si
->overlay
.myBuffer
[offset
].buffer
== ob
->buffer
) break;
370 if (offset
< MAXBUFFERS
)
372 /* scaler input (values are in pixels) */
373 oc
->view
.h_alignment
= 0;
374 oc
->view
.v_alignment
= 0;
379 /* Note: this has to be in sync with the slopspace setup during buffer allocation.. */
380 oc
->view
.width_alignment
= 7;
383 /* we should not be here, but set the worst-case value just to be safe anyway */
384 oc
->view
.width_alignment
= 7;
388 oc
->view
.height_alignment
= 0;
389 oc
->view
.width
.min
= 1;
390 oc
->view
.height
.min
= 2; /* two fields */
391 oc
->view
.width
.max
= ob
->width
;
392 oc
->view
.height
.max
= ob
->height
;
394 /* scaler output restrictions */
395 oc
->window
.h_alignment
= 0;
396 oc
->window
.v_alignment
= 0;
397 oc
->window
.width_alignment
= 0;
398 oc
->window
.height_alignment
= 0;
399 oc
->window
.width
.min
= 2;
400 /* GeForce cards can output upto and including 2046 pixels in width */
401 //fixme: how about TNT?
402 if (dm
->virtual_width
> 2046)
404 oc
->window
.width
.max
= 2046;
408 oc
->window
.width
.max
= dm
->virtual_width
;
410 oc
->window
.height
.min
= 2;
411 /* GeForce cards can output upto and including 2046 pixels in height */
412 //fixme: how about TNT?
413 if (dm
->virtual_height
> 2046)
415 oc
->window
.height
.max
= 2046;
419 oc
->window
.height
.max
= dm
->virtual_height
;
422 /* VIA scaling restrictions */
423 /* VIA has a 'tricked' 1/16 minimum */
424 oc
->h_scale
.min
= 0.0625;
425 oc
->v_scale
.min
= 0.0625;
426 /* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */
428 oc
->h_scale
.max
= 8.0;
429 oc
->v_scale
.max
= 8.0;
435 /* this is no buffer of ours! */
436 LOG(4,("Overlay: Get_overlay_constraints: buffer is not ours, aborted!\n"));
442 overlay_token
ALLOCATE_OVERLAY(void)
445 LOG(4,("Overlay: Allocate_overlay called: "));
447 /* come up with a token */
448 tmpToken
= 0x12345678;
450 /* acquire the shared benaphore */
451 AQUIRE_BEN(si
->overlay
.lock
)
453 /* overlay unit already in use? */
454 if (si
->overlay
.myToken
== NULL
)
455 /* overlay unit is available */
457 LOG(4,("succesfull\n"));
459 si
->overlay
.myToken
= &tmpToken
;
461 /* release the shared benaphore */
462 RELEASE_BEN(si
->overlay
.lock
)
464 return si
->overlay
.myToken
;
467 /* sorry, overlay unit is occupied */
469 LOG(4,("failed: already in use!\n"));
471 /* release the shared benaphore */
472 RELEASE_BEN(si
->overlay
.lock
)
478 status_t
RELEASE_OVERLAY(overlay_token ot
)
480 LOG(4,("Overlay: Release_overlay called: "));
482 /* is this call for real? */
483 if ((ot
== NULL
) || (si
->overlay
.myToken
== NULL
) || (ot
!= si
->overlay
.myToken
))
486 LOG(4,("failed, not in use!\n"));
491 /* call is for real */
496 LOG(4,("succesfull\n"));
498 si
->overlay
.myToken
= NULL
;
503 status_t CONFIGURE_OVERLAY
504 (overlay_token ot
, const overlay_buffer
*ob
, const overlay_window
*ow
, const overlay_view
*ov
)
506 int offset
= 0; /* used for buffer index */
508 LOG(4,("Overlay: Configure_overlay called: "));
511 * When a Workspace switch, screen prefs change, or overlay app shutdown occurs, BeOS will
512 * release all overlay buffers. The buffer currently displayed at that moment, may need some
513 * 'hardware releasing' in the CONFIGURE_OVERLAY routine. This is why CONFIGURE_OVERLAY gets
514 * called one more time then, with a null pointer for overlay_window and overlay_view, while
515 * the currently displayed overlay_buffer is given.
516 * The G200-G550 do not need to do anything on such an occasion, so we simply return if we
517 * get called then. */
518 if ((ow
== NULL
) || (ov
== NULL
))
520 LOG(4,("output properties changed\n"));
526 * If during overlay use the screen prefs are changed, or the workspace has changed, it
527 * may be that we were not able to re-allocate the requested overlay buffers (or only partly)
528 * due to lack of cardRAM. If the app does not respond properly to this, we might end up
529 * with a NULL pointer instead of a overlay_buffer to work with here.
530 * Of course, we need to abort then to prevent the system from 'going down'.
531 * The app will probably crash because it will want to write into this non-existant buffer
535 LOG(4,("no overlay buffer specified\n"));
540 /* is this call done by the app that owns us? */
541 if ((ot
== NULL
) || (si
->overlay
.myToken
== NULL
) || (ot
!= si
->overlay
.myToken
))
549 /* call is for real */
551 /* find the buffer's offset */
552 for (offset
= 0; offset
< MAXBUFFERS
; offset
++)
554 if (si
->overlay
.myBuffer
[offset
].buffer
== ob
->buffer
) break;
557 if (offset
< MAXBUFFERS
)
559 LOG(4,("succesfull, switching to buffer %d\n", offset
));
561 /* program overlay hardware */
562 eng_configure_bes(ob
, ow
, ov
, offset
);
568 /* this is no buffer of ours! */
569 LOG(4,("buffer is not ours, aborted!\n"));