1 /* 2 Haiku ATI video driver adapted from the X.org ATI driver which has the 3 following copyright: 4 5 Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, 6 Precision Insight, Inc., Cedar Park, Texas, and 7 VA Linux Systems Inc., Fremont, California. 8 9 Copyright 2011 Haiku, Inc. All rights reserved. 10 Distributed under the terms of the MIT license. 11 12 Authors: 13 Gerald Zajac 14 */ 15 16 #include "accelerant.h" 17 #include "rage128.h" 18 19 20 static uint32 sCurrentKeyColor = 0; 21 static uint32 sCurrentKeyMask = 0; 22 23 24 25 bool 26 Rage128_DisplayOverlay(const overlay_window* window, 27 const overlay_buffer* buffer) 28 { 29 // Return true if setup is successful. 30 31 SharedInfo& si = *gInfo.sharedInfo; 32 33 if (window == NULL || buffer == NULL) 34 return false; 35 36 if (buffer->space != B_YCbCr422) 37 return false; // color space not supported 38 39 uint32 keyColor = 0; 40 uint32 keyMask = 0; 41 42 switch (si.displayMode.bitsPerPixel) { 43 case 15: 44 keyMask = 0x7fff; 45 keyColor = (window->blue.value & window->blue.mask) << 0 46 | (window->green.value & window->green.mask) << 5 47 | (window->red.value & window->red.mask) << 10; 48 // 15 bit color has no alpha bits 49 break; 50 case 16: 51 keyMask = 0xffff; 52 keyColor = (window->blue.value & window->blue.mask) << 0 53 | (window->green.value & window->green.mask) << 5 54 | (window->red.value & window->red.mask) << 11; 55 // 16 bit color has no alpha bits 56 break; 57 default: 58 keyMask = 0xffffffff; 59 keyColor = (window->blue.value & window->blue.mask) << 0 60 | (window->green.value & window->green.mask) << 8 61 | (window->red.value & window->red.mask) << 16 62 | (window->alpha.value & window->alpha.mask) << 24; 63 break; 64 } 65 66 // If the key color or key mask has changed since the overlay was 67 // previously initialized, initialize it again. This is to avoid 68 // initializing the overlay video everytime the overlay buffer is 69 // switched which causes artifacts in the overlay display. 70 71 if (keyColor != sCurrentKeyColor || keyMask != sCurrentKeyMask) 72 { 73 TRACE("Rage128_DisplayOverlay() initializing overlay video\n"); 74 75 // Initialize the overlay video by first resetting the video. 76 77 OUTREG(R128_OV0_SCALE_CNTL, 0); 78 OUTREG(R128_OV0_EXCLUSIVE_HORZ, 0); 79 OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0); 80 OUTREG(R128_OV0_FILTER_CNTL, 0x0000000f); 81 82 const uint32 brightness = 0; 83 const uint32 saturation = 16; 84 OUTREG(R128_OV0_COLOUR_CNTL, brightness | saturation << 8 85 | saturation << 16); 86 87 OUTREG(R128_OV0_GRAPHICS_KEY_MSK, keyMask); 88 OUTREG(R128_OV0_GRAPHICS_KEY_CLR, keyColor); 89 OUTREG(R128_OV0_KEY_CNTL, R128_GRAPHIC_KEY_FN_NE); 90 OUTREG(R128_OV0_TEST, 0); 91 92 sCurrentKeyColor = keyColor; 93 sCurrentKeyMask = keyMask; 94 } 95 96 uint32 ecpDiv; 97 if (si.displayMode.timing.pixel_clock < 125000) 98 ecpDiv = 0; 99 else if (si.displayMode.timing.pixel_clock < 250000) 100 ecpDiv = 1; 101 else 102 ecpDiv = 2; 103 104 SetPLLReg(R128_VCLK_ECP_CNTL, ecpDiv << 8, R128_ECP_DIV_MASK); 105 106 int32 vertInc = (buffer->height << 20) / window->height; 107 int32 horzInc = (buffer->width << (12 + ecpDiv)) / window->width; 108 int32 stepBy = 1; 109 110 while (horzInc >= (2 << 12)) { 111 stepBy++; 112 horzInc >>= 1; 113 } 114 115 int32 x1 = window->h_start; 116 int32 y1 = window->v_start; 117 118 int32 x2 = window->h_start + window->width; 119 int32 y2 = window->v_start + window->height; 120 121 int32 left = x1; 122 int32 tmp = (left & 0x0003ffff) + 0x00028000 + (horzInc << 3); 123 int32 p1_h_accum_init = ((tmp << 4) & 0x000f8000) | 124 ((tmp << 12) & 0xf0000000); 125 126 tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (horzInc << 2); 127 int32 p23_h_accum_init = ((tmp << 4) & 0x000f8000) | 128 ((tmp << 12) & 0x70000000); 129 130 tmp = (y1 & 0x0000ffff) + 0x00018000; 131 int32 p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; 132 133 // Compute offset of overlay buffer in the video memory. 134 uint32 offset = (uint32)((addr_t)buffer->buffer - si.videoMemAddr); 135 136 OUTREG(R128_OV0_REG_LOAD_CNTL, 1); 137 while (!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))) 138 ; 139 140 OUTREG(R128_OV0_H_INC, horzInc | ((horzInc >> 1) << 16)); 141 OUTREG(R128_OV0_STEP_BY, stepBy | (stepBy << 8)); 142 OUTREG(R128_OV0_Y_X_START, x1 | y1 << 16); 143 OUTREG(R128_OV0_Y_X_END, x2 | y2 << 16); 144 OUTREG(R128_OV0_V_INC, vertInc); 145 OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 146 0x00000fff | ((buffer->height - 1) << 16)); 147 OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, buffer->bytes_per_row); 148 149 int32 width = window->width; 150 left = 0; 151 OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); 152 width >>= 1; 153 OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16)); 154 OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16)); 155 OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset); 156 OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); 157 OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0); 158 OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); 159 OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); 160 161 OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03); 162 OUTREG(R128_OV0_REG_LOAD_CNTL, 0); 163 164 return true; 165 } 166 167 168 void 169 Rage128_StopOverlay(void) 170 { 171 OUTREG(R128_OV0_SCALE_CNTL, 0); // reset the video 172 173 // Reset the key color and mask so that when the overlay is started again 174 // it will be initialized. 175 176 sCurrentKeyColor = 0; 177 sCurrentKeyMask = 0; 178 } 179