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
SuppressArtifacts(void * dataPtr)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
InitCommon(int fileDesc)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
UninitCommon(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
InitAccelerant(int fileDesc)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
AccelerantCloneInfoSize(void)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
GetAccelerantCloneInfo(void * data)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
CloneAccelerant(void * data)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
UninitAccelerant(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
GetAccelerantDeviceInfo(accelerant_device_info * adi)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