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