2 * Copyright 2010 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT license.
9 #include "accelerant.h"
17 OverlayCount(const display_mode
*mode
)
19 (void)mode
; // avoid compiler warning for unused arg
26 OverlaySupportedSpaces(const display_mode
* mode
)
28 (void)mode
; // avoid compiler warning for unused arg
30 static const uint32 kSupportedSpaces
[] = {B_RGB16
, B_YCbCr422
, 0};
32 return kSupportedSpaces
;
37 OverlaySupportedFeatures(uint32 colorSpace
)
39 (void)colorSpace
; // avoid compiler warning for unused arg
41 return B_OVERLAY_COLOR_KEY
42 | B_OVERLAY_HORIZONTAL_FILTERING
43 | B_OVERLAY_VERTICAL_FILTERING
;
48 AllocateOverlayBuffer(color_space colorSpace
, uint16 width
, uint16 height
)
50 SharedInfo
& si
= *gInfo
.sharedInfo
;
52 TRACE("AllocateOverlayBuffer() width %u, height %u, colorSpace 0x%lx\n",
53 width
, height
, colorSpace
);
55 si
.overlayLock
.Acquire();
57 // Note: When allocating buffers, buffer allocation starts at the end of
58 // video memory, and works backward to the end of the video frame buffer.
59 // The allocated buffers are recorded in a linked list of OverlayBuffer
60 // objects which are ordered by the buffer address with the first object
61 // in the list having the highest buffer address.
71 si
.overlayLock
.Release();
72 TRACE("AllocateOverlayBuffer() unsupported color space 0x%x\n",
77 // Calculate required buffer size as a multiple of 1K.
78 uint32 buffSize
= (width
* bytesPerPixel
* height
+ 0x3ff) & ~0x3ff;
80 // If the buffer area starts at the end of the video memory, the Voodoo5
81 // chip has the following display problems: displays a pink/red band at
82 // the bottom of the overlay display, leaves some artifacts at the top of
83 // screen, and messes up the displayed cursor when a hardware cursor is
84 // used (cursor image is at beginning of video memory). I don't know
85 // whether the Voodoo5 goes beyond the buffer area or whether this is some
86 // sort of memory mapping problem; nevertheless, adding 4k or 8K to the
87 // buffer size solves the problem. Thus, 16K is added to the buffer size.
89 if (si
.chipType
== VOODOO_5
)
90 buffSize
+= 16 * 1024;
92 OverlayBuffer
* ovBuff
= si
.overlayBuffer
;
93 OverlayBuffer
* prevOvBuff
= NULL
;
95 // If no buffers have been allocated, prevBuffAddr calculated here will be
96 // the address where the buffer area will start.
98 uint32 prevBuffAddr
= si
.videoMemAddr
+ si
.frameBufferOffset
99 + si
.maxFrameBufferSize
;
101 while (ovBuff
!= NULL
) {
102 // Test if there is sufficient space between the end of the current
103 // buffer and the start of the previous buffer to allocate the new
106 uint32 currentBuffEndAddr
= (addr_t
)ovBuff
->buffer
+ ovBuff
->size
;
107 if ((prevBuffAddr
- currentBuffEndAddr
) >= buffSize
)
108 break; // sufficient space for the new buffer
110 prevBuffAddr
= (uint32
)ovBuff
->buffer
;
112 ovBuff
= ovBuff
->nextBuffer
;
115 OverlayBuffer
* nextOvBuff
= ovBuff
;
117 if (ovBuff
== NULL
) {
118 // No space between any current buffers of the required size was found;
119 // thus space must be allocated between the last buffer and the end of
120 // the video frame buffer. Compute where current video frame buffer
121 // ends so that it can be determined if there is sufficient space for
122 // the new buffer to be created.
124 uint32 fbEndAddr
= si
.videoMemAddr
+ si
.frameBufferOffset
125 + (si
.displayMode
.virtual_width
* si
.displayMode
.bytesPerPixel
126 * si
.displayMode
.virtual_height
);
128 if (buffSize
> prevBuffAddr
- fbEndAddr
) {
129 si
.overlayLock
.Release();
130 TRACE("AllocateOverlayBuffer() insuffcient space for %ld (0x%lx) "
131 "byte buffer\n", buffSize
, buffSize
);
132 return NULL
; // insufficient space for buffer
138 ovBuff
= (OverlayBuffer
*)malloc(sizeof(OverlayBuffer
));
139 if (ovBuff
== NULL
) {
140 si
.overlayLock
.Release();
141 return NULL
; // memory not available for OverlayBuffer struct
144 ovBuff
->nextBuffer
= nextOvBuff
;
145 ovBuff
->size
= buffSize
;
146 ovBuff
->space
= colorSpace
;
147 ovBuff
->width
= width
;
148 ovBuff
->height
= height
;
149 ovBuff
->bytes_per_row
= width
* bytesPerPixel
;
150 ovBuff
->buffer
= (void*)(prevBuffAddr
- buffSize
);
151 ovBuff
->buffer_dma
= (void*)(si
.videoMemPCI
152 + ((addr_t
)ovBuff
->buffer
- si
.videoMemAddr
));
154 if (prevOvBuff
== NULL
)
155 si
.overlayBuffer
= ovBuff
;
157 prevOvBuff
->nextBuffer
= ovBuff
;
159 si
.overlayLock
.Release();
160 TRACE("AllocateOverlayBuffer() allocated %ld (0x%lx) byte buffer at 0x%lx\n",
161 buffSize
, buffSize
, ovBuff
->buffer
);
167 ReleaseOverlayBuffer(const overlay_buffer
* buffer
)
169 SharedInfo
& si
= *gInfo
.sharedInfo
;
171 TRACE("ReleaseOverlayBuffer() called\n");
176 // Find the buffer to be released.
178 OverlayBuffer
* ovBuff
= si
.overlayBuffer
;
179 OverlayBuffer
* prevOvBuff
= NULL
;
181 while (ovBuff
!= NULL
) {
182 if (ovBuff
->buffer
== buffer
->buffer
) {
183 // Buffer to be released has been found. Remove the OverlayBuffer
184 // object from the chain of overlay buffers.
186 if (prevOvBuff
== NULL
)
187 si
.overlayBuffer
= ovBuff
->nextBuffer
;
189 prevOvBuff
->nextBuffer
= ovBuff
->nextBuffer
;
192 TRACE("ReleaseOverlayBuffer() return OK\n");
197 ovBuff
= ovBuff
->nextBuffer
;
200 return B_ERROR
; // buffer to be released not found in chain of buffers
205 GetOverlayConstraints(const display_mode
* mode
, const overlay_buffer
* buffer
,
206 overlay_constraints
* constraints
)
208 if ((mode
== NULL
) || (buffer
== NULL
) || (constraints
== NULL
))
211 // Position (values are in pixels)
212 constraints
->view
.h_alignment
= 0;
213 constraints
->view
.v_alignment
= 0;
215 switch (buffer
->space
) {
218 constraints
->view
.width_alignment
= 7;
221 TRACE("GetOverlayConstraints() color space 0x%x out of range\n",
226 constraints
->view
.height_alignment
= 0;
229 constraints
->view
.width
.min
= 4;
230 constraints
->view
.height
.min
= 4;
231 constraints
->view
.width
.max
= buffer
->width
;
232 constraints
->view
.height
.max
= buffer
->height
;
234 // Scaler output restrictions
235 constraints
->window
.h_alignment
= 0;
236 constraints
->window
.v_alignment
= 0;
237 constraints
->window
.width_alignment
= 0;
238 constraints
->window
.height_alignment
= 0;
239 constraints
->window
.width
.min
= 2;
240 constraints
->window
.width
.max
= mode
->virtual_width
;
241 constraints
->window
.height
.min
= 2;
242 constraints
->window
.height
.max
= mode
->virtual_height
;
244 constraints
->h_scale
.min
= 1.0;
245 constraints
->h_scale
.max
= 8.0;
246 constraints
->v_scale
.min
= 1.0;
247 constraints
->v_scale
.max
= 8.0;
254 AllocateOverlay(void)
256 SharedInfo
& si
= *gInfo
.sharedInfo
;
258 TRACE("AllocateOverlay() called\n");
260 // There is only a single overlay channel; thus, check if it is already
263 if (atomic_or(&si
.overlayAllocated
, 1) != 0) {
264 TRACE("AllocateOverlay() overlay channel already in use\n");
267 TRACE("AllocateOverlay() Overlay allocated, overlayToken: %d\n",
269 return (overlay_token
)++si
.overlayToken
;
274 ReleaseOverlay(overlay_token overlayToken
)
276 SharedInfo
& si
= *gInfo
.sharedInfo
;
278 TRACE("ReleaseOverlay() called\n");
280 if (overlayToken
!= (overlay_token
)si
.overlayToken
)
285 atomic_and(&si
.overlayAllocated
, 0); // mark overlay as unallocated
287 TRACE("ReleaseOverlay() return OK\n");
293 ConfigureOverlay (overlay_token overlayToken
, const overlay_buffer
* buffer
,
294 const overlay_window
* window
, const overlay_view
* view
)
296 SharedInfo
& si
= *gInfo
.sharedInfo
;
298 if (overlayToken
!= (overlay_token
)si
.overlayToken
)
304 if (window
== NULL
|| view
== NULL
) {
306 TRACE("ConfigureOverlay() hide only\n");
310 // Program the overlay hardware.
311 if (!TDFX_DisplayOverlay(window
, buffer
, view
)) {
312 TRACE("ConfigureOverlay(), call to TDFX_DisplayOverlay() returned error\n");