1 /*
2 * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 *
8 * The phase coefficient computation was taken from the X driver written by
9 * Alan Hourihane and David Dawes.
10 */
11
12
13 #include "accelerant.h"
14 #include "accelerant_protos.h"
15 #include "commands.h"
16
17 #include <Debug.h>
18 #include <math.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include <AGP.h>
23
24
25 #undef TRACE
26 //#define TRACE_OVERLAY
27 #ifdef TRACE_OVERLAY
28 # define TRACE(x...) _sPrintf("intel_extreme: " x)
29 #else
30 # define TRACE(x...)
31 #endif
32
33 #define ERROR(x...) _sPrintf("intel_extreme: " x)
34 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
35
36
37 #define NUM_HORIZONTAL_TAPS 5
38 #define NUM_VERTICAL_TAPS 3
39 #define NUM_HORIZONTAL_UV_TAPS 3
40 #define NUM_VERTICAL_UV_TAPS 3
41 #define NUM_PHASES 17
42 #define MAX_TAPS 5
43
44 struct phase_coefficient {
45 uint8 sign;
46 uint8 exponent;
47 uint16 mantissa;
48 };
49
50
51 /*! Splits the coefficient floating point value into the 3 components
52 sign, mantissa, and exponent.
53 */
54 static bool
split_coefficient(double & coefficient,int32 mantissaSize,phase_coefficient & splitCoefficient)55 split_coefficient(double &coefficient, int32 mantissaSize,
56 phase_coefficient &splitCoefficient)
57 {
58 double absCoefficient = fabs(coefficient);
59
60 int sign;
61 if (coefficient < 0.0)
62 sign = 1;
63 else
64 sign = 0;
65
66 int32 intCoefficient, res;
67 int32 maxValue = 1 << mantissaSize;
68 res = 12 - mantissaSize;
69
70 if ((intCoefficient = (int)(absCoefficient * 4 * maxValue + 0.5))
71 < maxValue) {
72 splitCoefficient.exponent = 3;
73 splitCoefficient.mantissa = intCoefficient << res;
74 coefficient = (double)intCoefficient / (double)(4 * maxValue);
75 } else if ((intCoefficient = (int)(absCoefficient * 2 * maxValue + 0.5))
76 < maxValue) {
77 splitCoefficient.exponent = 2;
78 splitCoefficient.mantissa = intCoefficient << res;
79 coefficient = (double)intCoefficient / (double)(2 * maxValue);
80 } else if ((intCoefficient = (int)(absCoefficient * maxValue + 0.5))
81 < maxValue) {
82 splitCoefficient.exponent = 1;
83 splitCoefficient.mantissa = intCoefficient << res;
84 coefficient = (double)intCoefficient / (double)maxValue;
85 } else if ((intCoefficient = (int)(absCoefficient * maxValue * 0.5 + 0.5))
86 < maxValue) {
87 splitCoefficient.exponent = 0;
88 splitCoefficient.mantissa = intCoefficient << res;
89 coefficient = (double)intCoefficient / (double)(maxValue / 2);
90 } else {
91 // coefficient out of range
92 return false;
93 }
94
95 splitCoefficient.sign = sign;
96 if (sign)
97 coefficient = -coefficient;
98
99 return true;
100 }
101
102
103 static void
update_coefficients(int32 taps,double filterCutOff,bool horizontal,bool isY,phase_coefficient * splitCoefficients)104 update_coefficients(int32 taps, double filterCutOff, bool horizontal, bool isY,
105 phase_coefficient* splitCoefficients)
106 {
107 if (filterCutOff < 1)
108 filterCutOff = 1;
109 if (filterCutOff > 3)
110 filterCutOff = 3;
111
112 bool isVerticalUV = !horizontal && !isY;
113 int32 mantissaSize = horizontal ? 7 : 6;
114
115 double rawCoefficients[MAX_TAPS * 32], coefficients[NUM_PHASES][MAX_TAPS];
116
117 int32 num = taps * 16;
118 for (int32 i = 0; i < num * 2; i++) {
119 double sinc;
120 double value = (1.0 / filterCutOff) * taps * M_PI * (i - num)
121 / (2 * num);
122 if (value == 0.0)
123 sinc = 1.0;
124 else
125 sinc = sin(value) / value;
126
127 // Hamming window
128 double window = (0.5 - 0.5 * cos(i * M_PI / num));
129 rawCoefficients[i] = sinc * window;
130 }
131
132 for (int32 i = 0; i < NUM_PHASES; i++) {
133 // Normalise the coefficients
134 double sum = 0.0;
135 int32 pos;
136 for (int32 j = 0; j < taps; j++) {
137 pos = i + j * 32;
138 sum += rawCoefficients[pos];
139 }
140 for (int32 j = 0; j < taps; j++) {
141 pos = i + j * 32;
142 coefficients[i][j] = rawCoefficients[pos] / sum;
143 }
144
145 // split them into sign/mantissa/exponent
146 for (int32 j = 0; j < taps; j++) {
147 pos = j + i * taps;
148
149 split_coefficient(coefficients[i][j], mantissaSize
150 + (((j == (taps - 1) / 2) && !isVerticalUV) ? 2 : 0),
151 splitCoefficients[pos]);
152 }
153
154 int32 tapAdjust[MAX_TAPS];
155 tapAdjust[0] = (taps - 1) / 2;
156 for (int32 j = 1, k = 1; j <= tapAdjust[0]; j++, k++) {
157 tapAdjust[k] = tapAdjust[0] - j;
158 tapAdjust[++k] = tapAdjust[0] + j;
159 }
160
161 // Adjust the coefficients
162 sum = 0.0;
163 for (int32 j = 0; j < taps; j++) {
164 sum += coefficients[i][j];
165 }
166
167 if (sum != 1.0) {
168 for (int32 k = 0; k < taps; k++) {
169 int32 tap2Fix = tapAdjust[k];
170 double diff = 1.0 - sum;
171
172 coefficients[i][tap2Fix] += diff;
173 pos = tap2Fix + i * taps;
174
175 split_coefficient(coefficients[i][tap2Fix], mantissaSize
176 + (((tap2Fix == (taps - 1) / 2) && !isVerticalUV) ? 2 : 0),
177 splitCoefficients[pos]);
178
179 sum = 0.0;
180 for (int32 j = 0; j < taps; j++) {
181 sum += coefficients[i][j];
182 }
183 if (sum == 1.0)
184 break;
185 }
186 }
187 }
188 }
189
190
191 static void
set_color_key(uint8 red,uint8 green,uint8 blue,uint8 redMask,uint8 greenMask,uint8 blueMask)192 set_color_key(uint8 red, uint8 green, uint8 blue, uint8 redMask,
193 uint8 greenMask, uint8 blueMask)
194 {
195 overlay_registers* registers = gInfo->overlay_registers;
196
197 registers->color_key_red = red;
198 registers->color_key_green = green;
199 registers->color_key_blue = blue;
200 registers->color_key_mask_red = ~redMask;
201 registers->color_key_mask_green = ~greenMask;
202 registers->color_key_mask_blue = ~blueMask;
203 registers->color_key_enabled = true;
204 }
205
206
207 static void
set_color_key(const overlay_window * window)208 set_color_key(const overlay_window* window)
209 {
210 switch (gInfo->shared_info->current_mode.space) {
211 case B_CMAP8:
212 set_color_key(0, 0, window->blue.value, 0x0, 0x0, 0xff);
213 break;
214 case B_RGB15:
215 set_color_key(window->red.value << 3, window->green.value << 3,
216 window->blue.value << 3, window->red.mask << 3,
217 window->green.mask << 3, window->blue.mask << 3);
218 break;
219 case B_RGB16:
220 set_color_key(window->red.value << 3, window->green.value << 2,
221 window->blue.value << 3, window->red.mask << 3,
222 window->green.mask << 2, window->blue.mask << 3);
223 break;
224
225 default:
226 set_color_key(window->red.value, window->green.value,
227 window->blue.value, window->red.mask, window->green.mask,
228 window->blue.mask);
229 break;
230 }
231 }
232
233
234 static void
update_overlay(bool updateCoefficients)235 update_overlay(bool updateCoefficients)
236 {
237 if (!gInfo->shared_info->overlay_active
238 || gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965))
239 return;
240
241 QueueCommands queue(gInfo->shared_info->primary_ring_buffer);
242 queue.PutFlush();
243 queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
244 queue.PutOverlayFlip(COMMAND_OVERLAY_CONTINUE, updateCoefficients);
245
246 // make sure the flip is done now
247 queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
248 queue.PutFlush();
249
250 TRACE("%s: UP: %lx, TST: %lx, ST: %lx, CMD: %lx (%lx), ERR: %lx\n",
251 __func__, read32(INTEL_OVERLAY_UPDATE),
252 read32(INTEL_OVERLAY_TEST), read32(INTEL_OVERLAY_STATUS),
253 *(((uint32*)gInfo->overlay_registers) + 0x68/4), read32(0x30168),
254 read32(0x2024));
255 }
256
257
258 static void
show_overlay(void)259 show_overlay(void)
260 {
261 if (gInfo->shared_info->overlay_active
262 || gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965))
263 return;
264
265 gInfo->shared_info->overlay_active = true;
266 gInfo->overlay_registers->overlay_enabled = true;
267
268 QueueCommands queue(gInfo->shared_info->primary_ring_buffer);
269 queue.PutOverlayFlip(COMMAND_OVERLAY_ON, true);
270 queue.PutFlush();
271
272 TRACE("%s: UP: %lx, TST: %lx, ST: %lx, CMD: %lx (%lx), ERR: %lx\n",
273 __func__, read32(INTEL_OVERLAY_UPDATE),
274 read32(INTEL_OVERLAY_TEST), read32(INTEL_OVERLAY_STATUS),
275 *(((uint32*)gInfo->overlay_registers) + 0x68/4),
276 read32(0x30168), read32(0x2024));
277 }
278
279
280 static void
hide_overlay(void)281 hide_overlay(void)
282 {
283 if (!gInfo->shared_info->overlay_active
284 || gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965))
285 return;
286
287 overlay_registers* registers = gInfo->overlay_registers;
288
289 gInfo->shared_info->overlay_active = false;
290 registers->overlay_enabled = false;
291
292 QueueCommands queue(gInfo->shared_info->primary_ring_buffer);
293
294 // flush pending commands
295 queue.PutFlush();
296 queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
297
298 // clear overlay enabled bit
299 queue.PutOverlayFlip(COMMAND_OVERLAY_CONTINUE, false);
300 queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
301
302 // turn off overlay engine
303 queue.PutOverlayFlip(COMMAND_OVERLAY_OFF, false);
304 queue.PutWaitFor(COMMAND_WAIT_FOR_OVERLAY_FLIP);
305
306 gInfo->current_overlay = NULL;
307 }
308
309
310 // #pragma mark -
311
312
313 uint32
intel_overlay_count(const display_mode * mode)314 intel_overlay_count(const display_mode* mode)
315 {
316 // TODO: make this depending on the amount of RAM and the screen mode
317 // (and we could even have more than one when using 3D as well)
318 return 1;
319 }
320
321
322 const uint32*
intel_overlay_supported_spaces(const display_mode * mode)323 intel_overlay_supported_spaces(const display_mode* mode)
324 {
325 static const uint32 kSupportedSpaces[] = {B_RGB15, B_RGB16, B_RGB32,
326 B_YCbCr422, 0};
327 static const uint32 kSupportedi965Spaces[] = {B_YCbCr422, 0};
328 intel_shared_info &sharedInfo = *gInfo->shared_info;
329
330 if (sharedInfo.device_type.InGroup(INTEL_GROUP_96x))
331 return kSupportedi965Spaces;
332
333 return kSupportedSpaces;
334 }
335
336
337 uint32
intel_overlay_supported_features(uint32 colorSpace)338 intel_overlay_supported_features(uint32 colorSpace)
339 {
340 return B_OVERLAY_COLOR_KEY
341 | B_OVERLAY_HORIZONTAL_FILTERING
342 | B_OVERLAY_VERTICAL_FILTERING
343 | B_OVERLAY_HORIZONTAL_MIRRORING;
344 }
345
346
347 const overlay_buffer*
intel_allocate_overlay_buffer(color_space colorSpace,uint16 width,uint16 height)348 intel_allocate_overlay_buffer(color_space colorSpace, uint16 width,
349 uint16 height)
350 {
351 TRACE("%s(width %u, height %u, colorSpace %lu)\n", __func__, width,
352 height, colorSpace);
353
354 intel_shared_info &sharedInfo = *gInfo->shared_info;
355 uint32 bytesPerPixel;
356
357 switch (colorSpace) {
358 case B_RGB15:
359 bytesPerPixel = 2;
360 break;
361 case B_RGB16:
362 bytesPerPixel = 2;
363 break;
364 case B_RGB32:
365 bytesPerPixel = 4;
366 break;
367 case B_YCbCr422:
368 bytesPerPixel = 2;
369 break;
370 default:
371 return NULL;
372 }
373
374 struct overlay* overlay = (struct overlay*)malloc(sizeof(struct overlay));
375 if (overlay == NULL)
376 return NULL;
377
378 // TODO: locking!
379
380 // alloc graphics mem
381
382 int32 alignment = 0x3f;
383 if (sharedInfo.device_type.IsModel(INTEL_MODEL_965))
384 alignment = 0xff;
385
386 overlay_buffer* buffer = &overlay->buffer;
387 buffer->space = colorSpace;
388 buffer->width = width;
389 buffer->height = height;
390 buffer->bytes_per_row = (width * bytesPerPixel + alignment) & ~alignment;
391
392 status_t status = intel_allocate_memory(buffer->bytes_per_row * height,
393 0, overlay->buffer_base);
394 if (status < B_OK) {
395 free(overlay);
396 return NULL;
397 }
398
399 if (sharedInfo.device_type.IsModel(INTEL_MODEL_965)) {
400 status = intel_allocate_memory(INTEL_i965_OVERLAY_STATE_SIZE,
401 B_APERTURE_NON_RESERVED, overlay->state_base);
402 if (status < B_OK) {
403 intel_free_memory(overlay->buffer_base);
404 free(overlay);
405 return NULL;
406 }
407
408 overlay->state_offset = overlay->state_base
409 - (addr_t)gInfo->shared_info->graphics_memory;
410 }
411
412 overlay->buffer_offset = overlay->buffer_base
413 - (addr_t)gInfo->shared_info->graphics_memory;
414
415 buffer->buffer = (uint8*)overlay->buffer_base;
416 buffer->buffer_dma = (uint8*)gInfo->shared_info->physical_graphics_memory
417 + overlay->buffer_offset;
418
419 TRACE("%s: base=%x, offset=%x, address=%x, physical address=%x\n",
420 __func__, overlay->buffer_base, overlay->buffer_offset,
421 buffer->buffer, buffer->buffer_dma);
422
423 return buffer;
424 }
425
426
427 status_t
intel_release_overlay_buffer(const overlay_buffer * buffer)428 intel_release_overlay_buffer(const overlay_buffer* buffer)
429 {
430 CALLED();
431
432 struct overlay* overlay = (struct overlay*)buffer;
433
434 // TODO: locking!
435
436 if (gInfo->current_overlay == overlay)
437 hide_overlay();
438
439 intel_free_memory(overlay->buffer_base);
440 if (gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965))
441 intel_free_memory(overlay->state_base);
442 free(overlay);
443
444 return B_OK;
445 }
446
447
448 status_t
intel_get_overlay_constraints(const display_mode * mode,const overlay_buffer * buffer,overlay_constraints * constraints)449 intel_get_overlay_constraints(const display_mode* mode,
450 const overlay_buffer* buffer, overlay_constraints* constraints)
451 {
452 CALLED();
453
454 // taken from the Radeon driver...
455
456 // scaler input restrictions
457 // TODO: check all these values; most of them are probably too restrictive
458
459 // position
460 constraints->view.h_alignment = 0;
461 constraints->view.v_alignment = 0;
462
463 // alignment
464 switch (buffer->space) {
465 case B_RGB15:
466 constraints->view.width_alignment = 7;
467 break;
468 case B_RGB16:
469 constraints->view.width_alignment = 7;
470 break;
471 case B_RGB32:
472 constraints->view.width_alignment = 3;
473 break;
474 case B_YCbCr422:
475 constraints->view.width_alignment = 7;
476 break;
477 case B_YUV12:
478 constraints->view.width_alignment = 7;
479 break;
480 default:
481 return B_BAD_VALUE;
482 }
483 constraints->view.height_alignment = 0;
484
485 // size
486 constraints->view.width.min = 4; // make 4-tap filter happy
487 constraints->view.height.min = 4;
488 constraints->view.width.max = buffer->width;
489 constraints->view.height.max = buffer->height;
490
491 // scaler output restrictions
492 constraints->window.h_alignment = 0;
493 constraints->window.v_alignment = 0;
494 constraints->window.width_alignment = 0;
495 constraints->window.height_alignment = 0;
496 constraints->window.width.min = 2;
497 constraints->window.width.max = mode->virtual_width;
498 constraints->window.height.min = 2;
499 constraints->window.height.max = mode->virtual_height;
500
501 // TODO: the minimum values are not tested
502 constraints->h_scale.min = 1.0f / (1 << 4);
503 constraints->h_scale.max = buffer->width * 7;
504 constraints->v_scale.min = 1.0f / (1 << 4);
505 constraints->v_scale.max = buffer->height * 7;
506
507 return B_OK;
508 }
509
510
511 overlay_token
intel_allocate_overlay(void)512 intel_allocate_overlay(void)
513 {
514 CALLED();
515
516 // we only have a single overlay channel
517 if (atomic_or(&gInfo->shared_info->overlay_channel_used, 1) != 0)
518 return NULL;
519
520 return (overlay_token)++gInfo->shared_info->overlay_token;
521 }
522
523
524 status_t
intel_release_overlay(overlay_token overlayToken)525 intel_release_overlay(overlay_token overlayToken)
526 {
527 CALLED();
528
529 // we only have a single token, which simplifies this
530 if (overlayToken != (overlay_token)gInfo->shared_info->overlay_token)
531 return B_BAD_VALUE;
532
533 atomic_and(&gInfo->shared_info->overlay_channel_used, 0);
534
535 return B_OK;
536 }
537
538
539 status_t
intel_configure_overlay(overlay_token overlayToken,const overlay_buffer * buffer,const overlay_window * window,const overlay_view * view)540 intel_configure_overlay(overlay_token overlayToken,
541 const overlay_buffer* buffer, const overlay_window* window,
542 const overlay_view* view)
543 {
544 CALLED();
545
546 if (overlayToken != (overlay_token)gInfo->shared_info->overlay_token)
547 return B_BAD_VALUE;
548
549 if (window == NULL || view == NULL) {
550 hide_overlay();
551 return B_OK;
552 }
553
554 struct overlay* overlay = (struct overlay*)buffer;
555 overlay_registers* registers = gInfo->overlay_registers;
556 intel_shared_info &sharedInfo = *gInfo->shared_info;
557 bool updateCoefficients = false;
558 uint32 bytesPerPixel = 2;
559
560 switch (buffer->space) {
561 case B_RGB15:
562 registers->source_format = OVERLAY_FORMAT_RGB15;
563 break;
564 case B_RGB16:
565 registers->source_format = OVERLAY_FORMAT_RGB16;
566 break;
567 case B_RGB32:
568 registers->source_format = OVERLAY_FORMAT_RGB32;
569 bytesPerPixel = 4;
570 break;
571 case B_YCbCr422:
572 registers->source_format = OVERLAY_FORMAT_YCbCr422;
573 break;
574 }
575
576 if (!gInfo->shared_info->overlay_active
577 || memcmp(&gInfo->last_overlay_view, view, sizeof(overlay_view)) != 0
578 || memcmp(&gInfo->last_overlay_frame, window, sizeof(overlay_frame)) != 0) {
579 // scaling has changed, program window and scaling factor
580
581 // clip the window to on screen bounds
582 // TODO: this is not yet complete or correct - especially if we start
583 // to support moving the display!
584 int32 left, top, right, bottom;
585 left = window->h_start;
586 right = window->h_start + window->width;
587 top = window->v_start;
588 bottom = window->v_start + window->height;
589 if (left < 0)
590 left = 0;
591 if (top < 0)
592 top = 0;
593 if (right > sharedInfo.current_mode.timing.h_display)
594 right = sharedInfo.current_mode.timing.h_display;
595 if (bottom > sharedInfo.current_mode.timing.v_display)
596 bottom = sharedInfo.current_mode.timing.v_display;
597 if (left >= right || top >= bottom) {
598 // overlay is not within visible bounds
599 hide_overlay();
600 return B_OK;
601 }
602
603 registers->window_left = left;
604 registers->window_top = top;
605 registers->window_width = right - left;
606 registers->window_height = bottom - top;
607
608 uint32 horizontalScale = (view->width << 12) / window->width;
609 uint32 verticalScale = (view->height << 12) / window->height;
610 uint32 horizontalScaleUV = horizontalScale >> 1;
611 uint32 verticalScaleUV = verticalScale >> 1;
612 horizontalScale = horizontalScaleUV << 1;
613 verticalScale = verticalScaleUV << 1;
614
615 // we need to offset the overlay view to adapt it to the clipping
616 // (in addition to whatever offset is desired already)
617 left = view->h_start - (int32)((window->h_start - left)
618 * (horizontalScale / 4096.0) + 0.5);
619 top = view->v_start - (int32)((window->v_start - top)
620 * (verticalScale / 4096.0) + 0.5);
621 right = view->h_start + view->width;
622 bottom = view->v_start + view->height;
623
624 gInfo->overlay_position_buffer_offset = buffer->bytes_per_row * top
625 + left * bytesPerPixel;
626
627 // Note: in non-planar mode, you *must* not program the source
628 // width/height UV registers - they must stay cleared, or the chip is
629 // doing strange stuff.
630 // On the other hand, you have to program the UV scaling registers, or
631 // the result will be wrong, too.
632 registers->source_width_rgb = right - left;
633 registers->source_height_rgb = bottom - top;
634 if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_8xx)) {
635 registers->source_bytes_per_row_rgb = (((overlay->buffer_offset
636 + (view->width << 1) + 0x1f) >> 5)
637 - (overlay->buffer_offset >> 5) - 1) << 2;
638 } else {
639 int yaddress = overlay->buffer_offset;
640 int yswidth = view->width << 1;
641 registers->source_bytes_per_row_rgb = (((((yaddress
642 + yswidth + 0x3f) >> 6) - (yaddress >> 6)) << 1) - 1) << 2;
643 }
644
645 // horizontal scaling
646 registers->scale_rgb.horizontal_downscale_factor
647 = horizontalScale >> 12;
648 registers->scale_rgb.horizontal_scale_fraction
649 = horizontalScale & 0xfff;
650 registers->scale_uv.horizontal_downscale_factor
651 = horizontalScaleUV >> 12;
652 registers->scale_uv.horizontal_scale_fraction
653 = horizontalScaleUV & 0xfff;
654
655 // vertical scaling
656 registers->scale_rgb.vertical_scale_fraction = verticalScale & 0xfff;
657 registers->scale_uv.vertical_scale_fraction = verticalScaleUV & 0xfff;
658 registers->vertical_scale_rgb = verticalScale >> 12;
659 registers->vertical_scale_uv = verticalScaleUV >> 12;
660
661 TRACE("scale: h = %ld.%ld, v = %ld.%ld\n", horizontalScale >> 12,
662 horizontalScale & 0xfff, verticalScale >> 12,
663 verticalScale & 0xfff);
664
665 if (verticalScale != gInfo->last_vertical_overlay_scale
666 || horizontalScale != gInfo->last_horizontal_overlay_scale) {
667 // Recompute phase coefficients (taken from X driver)
668 updateCoefficients = true;
669
670 phase_coefficient coefficients[NUM_HORIZONTAL_TAPS * NUM_PHASES];
671 update_coefficients(NUM_HORIZONTAL_TAPS, horizontalScale / 4096.0,
672 true, true, coefficients);
673
674 phase_coefficient coefficientsUV[
675 NUM_HORIZONTAL_UV_TAPS * NUM_PHASES];
676 update_coefficients(NUM_HORIZONTAL_UV_TAPS,
677 horizontalScaleUV / 4096.0, true, false, coefficientsUV);
678
679 int32 pos = 0;
680 for (int32 i = 0; i < NUM_PHASES; i++) {
681 for (int32 j = 0; j < NUM_HORIZONTAL_TAPS; j++) {
682 registers->horizontal_coefficients_rgb[pos]
683 = coefficients[pos].sign << 15
684 | coefficients[pos].exponent << 12
685 | coefficients[pos].mantissa;
686 pos++;
687 }
688 }
689
690 pos = 0;
691 for (int32 i = 0; i < NUM_PHASES; i++) {
692 for (int32 j = 0; j < NUM_HORIZONTAL_UV_TAPS; j++) {
693 registers->horizontal_coefficients_uv[pos]
694 = coefficientsUV[pos].sign << 15
695 | coefficientsUV[pos].exponent << 12
696 | coefficientsUV[pos].mantissa;
697 pos++;
698 }
699 }
700
701 gInfo->last_vertical_overlay_scale = verticalScale;
702 gInfo->last_horizontal_overlay_scale = horizontalScale;
703 }
704
705 gInfo->last_overlay_view = *view;
706 gInfo->last_overlay_frame = *(overlay_frame*)window;
707 }
708
709 registers->color_control_output_mode = true;
710 registers->select_pipe = 0;
711
712 // program buffer
713
714 registers->buffer_rgb0
715 = overlay->buffer_offset + gInfo->overlay_position_buffer_offset;
716 registers->stride_rgb = buffer->bytes_per_row;
717
718 registers->mirroring_mode
719 = (window->flags & B_OVERLAY_HORIZONTAL_MIRRORING) != 0
720 ? OVERLAY_MIRROR_HORIZONTAL : OVERLAY_MIRROR_NORMAL;
721 registers->ycbcr422_order = 0;
722
723 if (!gInfo->shared_info->overlay_active) {
724 // overlay is shown for the first time
725 set_color_key(window);
726 show_overlay();
727 } else
728 update_overlay(updateCoefficients);
729
730 gInfo->current_overlay = overlay;
731 return B_OK;
732 }
733
734