1 /* 2 * Copyright 2007-2012 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Gerald Zajac 7 */ 8 9 10 #include "accelerant.h" 11 12 #include <errno.h> 13 #include <string.h> 14 #include <unistd.h> 15 16 17 AccelerantInfo gInfo; // global data used by source files of accelerant 18 19 static uint32 videoValue; 20 21 22 static int32 23 SuppressArtifacts(void* dataPtr) 24 { 25 // The Intel 810 & 815 video chips create annoying artifacts which are 26 // most noticeable when the cursor is moved by itself or the user goes up 27 // and down through a menu. However, if a large number of video memory 28 // locations are accessed frequently like when the GLTeapot demo is 29 // running, the artifacts are greatly suppressed. Thus, that is the reason 30 // why this function accesses a large number of video memory locations 31 // frequently. Note that the accessed memory locations are at the end of 32 // the video memory. This is because some artifacts still occur at the 33 // top of the screen if the accessed memory is at the beginning of the 34 // video memory. 35 36 // Note that this function will reduce the general performance of a 37 // computer somewhat, but it is much less of a hit than if double 38 // buffering was used for the video. Base on the frame rate of the 39 // the GLTeapot demo, it is less than a 10% reduction. 40 41 SharedInfo& si = *((SharedInfo*)dataPtr); 42 43 while (true) { 44 uint32* src = ((uint32*)(si.videoMemAddr)) + si.videoMemSize / 4 - 1; 45 uint32 count = 65000; 46 47 while (count-- > 0) 48 videoValue = *src--; 49 50 snooze(30000); // sleep for 30 msec 51 } 52 53 return 0; 54 } 55 56 57 static status_t 58 InitCommon(int fileDesc) 59 { 60 // Initialization function used by primary and cloned accelerants. 61 62 gInfo.deviceFileDesc = fileDesc; 63 64 // Get area ID of shared data from driver. 65 66 area_id sharedArea; 67 status_t result = ioctl(gInfo.deviceFileDesc, INTEL_GET_SHARED_DATA, 68 &sharedArea, sizeof(sharedArea)); 69 if (result != B_OK) 70 return result; 71 72 gInfo.sharedInfoArea = clone_area("i810 shared info", 73 (void**)&(gInfo.sharedInfo), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, 74 sharedArea); 75 if (gInfo.sharedInfoArea < 0) 76 return gInfo.sharedInfoArea; // sharedInfoArea has error code 77 78 gInfo.regsArea = clone_area("i810 regs area", (void**)&(gInfo.regs), 79 B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gInfo.sharedInfo->regsArea); 80 if (gInfo.regsArea < 0) { 81 delete_area(gInfo.sharedInfoArea); 82 return gInfo.regsArea; // regsArea has error code 83 } 84 85 return B_OK; 86 } 87 88 89 static void 90 UninitCommon(void) 91 { 92 // This function is used by both primary and cloned accelerants. 93 94 delete_area(gInfo.regsArea); 95 gInfo.regs = 0; 96 97 delete_area(gInfo.sharedInfoArea); 98 gInfo.sharedInfo = 0; 99 } 100 101 102 status_t 103 InitAccelerant(int fileDesc) 104 { 105 // Initialize the accelerant. fileDesc is the file handle of the device 106 // (in /dev/graphics) that has been opened by the app_server. 107 108 TRACE("Enter InitAccelerant()\n"); 109 110 gInfo.bAccelerantIsClone = false; // indicate this is primary accelerant 111 112 status_t result = InitCommon(fileDesc); 113 if (result == B_OK) { 114 SharedInfo& si = *gInfo.sharedInfo; 115 116 TRACE("Vendor ID: 0x%X, Device ID: 0x%X\n", si.vendorID, si.deviceID); 117 118 // Ensure that InitAccelerant is executed just once (copies should be 119 // clones) 120 121 if (si.bAccelerantInUse) { 122 result = B_NOT_ALLOWED; 123 } else { 124 result = I810_Init(); // perform init related to current chip 125 if (result == B_OK) { 126 result = si.engineLock.Init("i810 engine lock"); 127 if (result == B_OK) { 128 // Ensure that this function won't be executed again 129 // (copies should be clones) 130 si.bAccelerantInUse = true; 131 132 thread_id threadID = spawn_thread(SuppressArtifacts, 133 "SuppressArtifacts_Thread", B_DISPLAY_PRIORITY, 134 gInfo.sharedInfo); 135 result = resume_thread(threadID); 136 } 137 } 138 } 139 140 if (result != B_OK) 141 UninitCommon(); 142 } 143 144 TRACE("Leave InitAccelerant(), result: 0x%X\n", result); 145 return result; 146 } 147 148 149 ssize_t 150 AccelerantCloneInfoSize(void) 151 { 152 // Return the number of bytes required to hold the information required 153 // to clone the device. The information is merely the name of the device; 154 // thus, return the size of the name buffer. 155 156 return B_OS_NAME_LENGTH; 157 } 158 159 160 void 161 GetAccelerantCloneInfo(void* data) 162 { 163 // Return the info required to clone the device. Argument data points to 164 // a buffer which is the size returned by AccelerantCloneInfoSize(). 165 166 ioctl(gInfo.deviceFileDesc, INTEL_DEVICE_NAME, data, B_OS_NAME_LENGTH); 167 } 168 169 170 status_t 171 CloneAccelerant(void* data) 172 { 173 // Initialize a copy of the accelerant as a clone. Argument data points to 174 // a copy of the data which was returned by GetAccelerantCloneInfo(). 175 176 TRACE("Enter CloneAccelerant()\n"); 177 178 char path[MAXPATHLEN] = "/dev/"; 179 strcat(path, (const char*)data); 180 181 gInfo.deviceFileDesc = open(path, B_READ_WRITE); // open the device 182 if (gInfo.deviceFileDesc < 0) 183 return errno; 184 185 gInfo.bAccelerantIsClone = true; 186 187 status_t result = InitCommon(gInfo.deviceFileDesc); 188 if (result != B_OK) { 189 close(gInfo.deviceFileDesc); 190 return result; 191 } 192 193 result = gInfo.modeListArea = clone_area("i810 cloned display_modes", 194 (void**) &gInfo.modeList, B_ANY_ADDRESS, B_READ_AREA, 195 gInfo.sharedInfo->modeArea); 196 if (result < 0) { 197 UninitCommon(); 198 close(gInfo.deviceFileDesc); 199 return result; 200 } 201 202 TRACE("Leave CloneAccelerant()\n"); 203 return B_OK; 204 } 205 206 207 void 208 UninitAccelerant(void) 209 { 210 delete_area(gInfo.modeListArea); 211 gInfo.modeList = NULL; 212 213 UninitCommon(); 214 215 if (gInfo.bAccelerantIsClone) 216 close(gInfo.deviceFileDesc); 217 } 218 219 220 status_t 221 GetAccelerantDeviceInfo(accelerant_device_info* adi) 222 { 223 // Get info about the device. 224 225 SharedInfo& si = *gInfo.sharedInfo; 226 227 adi->version = 1; 228 strcpy(adi->name, "Intel 810/815 chipset"); 229 strcpy(adi->chipset, si.chipName); 230 strcpy(adi->serial_no, "unknown"); 231 adi->memory = si.maxFrameBufferSize; 232 adi->dac_speed = 270; 233 234 return B_OK; 235 } 236