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