1 /* 2 * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <string.h> 7 8 #include <create_display_modes.h> 9 10 #include "accelerant_protos.h" 11 #include "accelerant.h" 12 #include "utility.h" 13 14 15 //#define TRACE_MODE 16 #ifdef TRACE_MODE 17 extern "C" void _sPrintf(const char *format, ...); 18 # define TRACE(x) _sPrintf x 19 #else 20 # define TRACE(x) ; 21 #endif 22 23 24 static uint32 25 get_color_space_for_depth(uint32 depth) 26 { 27 switch (depth) { 28 case 4: 29 return B_GRAY8; 30 // the app_server is smart enough to translate this to VGA mode 31 case 8: 32 return B_CMAP8; 33 case 15: 34 return B_RGB15; 35 case 16: 36 return B_RGB16; 37 case 24: 38 return B_RGB24; 39 case 32: 40 return B_RGB32; 41 } 42 43 return 0; 44 } 45 46 47 /*! Checks if the specified \a mode can be set using VESA. */ 48 static bool 49 is_mode_supported(display_mode *mode) 50 { 51 vesa_mode *modes = gInfo->vesa_modes; 52 53 for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) { 54 // search mode in VESA mode list 55 // TODO: list is ordered, we could use binary search 56 if (modes[i].width == mode->virtual_width 57 && modes[i].height == mode->virtual_height 58 && get_color_space_for_depth(modes[i].bits_per_pixel) 59 == mode->space) 60 return true; 61 } 62 63 return false; 64 } 65 66 67 /*! Creates the initial mode list of the primary accelerant. 68 It's called from vesa_init_accelerant(). 69 */ 70 status_t 71 create_mode_list(void) 72 { 73 const color_space kVesaSpaces[] = {B_RGB32_LITTLE, B_RGB24_LITTLE, 74 B_RGB16_LITTLE, B_RGB15_LITTLE, B_CMAP8}; 75 76 gInfo->mode_list_area = create_display_modes("vesa modes", NULL, NULL, 0, 77 kVesaSpaces, sizeof(kVesaSpaces) / sizeof(kVesaSpaces[0]), 78 is_mode_supported, &gInfo->mode_list, &gInfo->shared_info->mode_count); 79 if (gInfo->mode_list_area < B_OK) 80 return gInfo->mode_list_area; 81 82 gInfo->shared_info->mode_list_area = gInfo->mode_list_area; 83 return B_OK; 84 } 85 86 87 // #pragma mark - 88 89 90 uint32 91 vesa_accelerant_mode_count(void) 92 { 93 TRACE(("vesa_accelerant_mode_count()\n")); 94 return gInfo->shared_info->mode_count; 95 } 96 97 98 status_t 99 vesa_get_mode_list(display_mode *modeList) 100 { 101 TRACE(("vesa_get_mode_info()\n")); 102 memcpy(modeList, gInfo->mode_list, 103 gInfo->shared_info->mode_count * sizeof(display_mode)); 104 return B_OK; 105 } 106 107 108 status_t 109 vesa_propose_display_mode(display_mode *target, const display_mode *low, 110 const display_mode *high) 111 { 112 TRACE(("vesa_propose_display_mode()\n")); 113 114 // just search for the specified mode in the list 115 116 for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { 117 display_mode *current = &gInfo->mode_list[i]; 118 119 if (target->virtual_width != current->virtual_width 120 || target->virtual_height != current->virtual_height 121 || target->space != current->space) 122 continue; 123 124 *target = *current; 125 return B_OK; 126 } 127 return B_BAD_VALUE; 128 } 129 130 131 status_t 132 vesa_set_display_mode(display_mode *_mode) 133 { 134 TRACE(("vesa_set_display_mode()\n")); 135 136 display_mode mode = *_mode; 137 if (vesa_propose_display_mode(&mode, &mode, &mode) != B_OK) 138 return B_BAD_VALUE; 139 140 // ToDo: unless we have a VBE3 device, we can't change the display mode 141 return B_UNSUPPORTED; 142 } 143 144 145 status_t 146 vesa_get_display_mode(display_mode *_currentMode) 147 { 148 TRACE(("vesa_get_display_mode()\n")); 149 *_currentMode = gInfo->shared_info->current_mode; 150 return B_OK; 151 } 152 153 154 status_t 155 vesa_get_frame_buffer_config(frame_buffer_config *config) 156 { 157 TRACE(("vesa_get_frame_buffer_config()\n")); 158 159 config->frame_buffer = gInfo->shared_info->frame_buffer; 160 config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer; 161 config->bytes_per_row = gInfo->shared_info->bytes_per_row; 162 163 return B_OK; 164 } 165 166 167 status_t 168 vesa_get_pixel_clock_limits(display_mode *mode, uint32 *low, uint32 *high) 169 { 170 TRACE(("vesa_get_pixel_clock_limits()\n")); 171 172 // ToDo: do some real stuff here (taken from radeon driver) 173 uint32 total_pix = (uint32)mode->timing.h_total * (uint32)mode->timing.v_total; 174 uint32 clock_limit = 2000000; 175 176 /* lower limit of about 48Hz vertical refresh */ 177 *low = (total_pix * 48L) / 1000L; 178 if (*low > clock_limit) 179 return B_ERROR; 180 181 *high = clock_limit; 182 return B_OK; 183 } 184 185 186 status_t 187 vesa_move_display(uint16 h_display_start, uint16 v_display_start) 188 { 189 TRACE(("vesa_move_display()\n")); 190 return B_ERROR; 191 } 192 193 194 status_t 195 vesa_get_timing_constraints(display_timing_constraints *dtc) 196 { 197 TRACE(("vesa_get_timing_constraints()\n")); 198 return B_ERROR; 199 } 200 201 202 void 203 vesa_set_indexed_colors(uint count, uint8 first, uint8 *colors, uint32 flags) 204 { 205 TRACE(("vesa_set_indexed_colors()\n")); 206 vga_set_indexed_colors_args args; 207 args.first = first; 208 args.count = count; 209 args.colors = colors; 210 ioctl(gInfo->device, VGA_SET_INDEXED_COLORS, &args, sizeof(args)); 211 } 212 213