Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / i810 / i810screen.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 All Rights Reserved.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sub license, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
16 of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Keith Whitwell <keith@tungstengraphics.com>
31 *
32 */
33
34
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/framebuffer.h"
39 #include "main/renderbuffer.h"
40 #include "main/simple_list.h"
41 #include "utils.h"
42
43 #include "i810screen.h"
44 #include "i810_dri.h"
45
46 #include "i810state.h"
47 #include "i810tex.h"
48 #include "i810span.h"
49
50 #include "GL/internal/dri_interface.h"
51
52 static const __DRIconfig **
53 i810FillInModes( __DRIscreen *psp,
54 unsigned pixel_bits, unsigned depth_bits,
55 unsigned stencil_bits, GLboolean have_back_buffer )
56 {
57 __DRIconfig **configs;
58 __GLcontextModes * m;
59 unsigned depth_buffer_factor;
60 unsigned back_buffer_factor;
61 unsigned i;
62
63 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
64 * enough to add support. Basically, if a context is created with an
65 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
66 * will never be used.
67 */
68 static const GLenum back_buffer_modes[] = {
69 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
70 };
71
72 uint8_t depth_bits_array[2];
73 uint8_t stencil_bits_array[2];
74 uint8_t msaa_samples_array[1];
75
76 depth_bits_array[0] = depth_bits;
77 depth_bits_array[1] = depth_bits;
78
79 /* Just like with the accumulation buffer, always provide some modes
80 * with a stencil buffer. It will be a sw fallback, but some apps won't
81 * care about that.
82 */
83 stencil_bits_array[0] = 0;
84 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
85
86 msaa_samples_array[0] = 0;
87
88 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
89 back_buffer_factor = (have_back_buffer) ? 2 : 1;
90
91 configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
92 depth_bits_array, stencil_bits_array,
93 depth_buffer_factor,
94 back_buffer_modes, back_buffer_factor,
95 msaa_samples_array, 1);
96 if (configs == NULL) {
97 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
98 __func__, __LINE__ );
99 return NULL;
100 }
101
102 /* Mark the visual as slow if there are "fake" stencil bits.
103 */
104 for (i = 0; configs[i]; i++) {
105 m = &configs[i]->modes;
106 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
107 m->visualRating = GLX_SLOW_CONFIG;
108 }
109 }
110
111 return (const __DRIconfig **) configs;
112 }
113
114
115 /* static int i810_malloc_proxy_buf(drmBufMapPtr buffers) */
116 /* { */
117 /* char *buffer; */
118 /* drmBufPtr buf; */
119 /* int i; */
120
121 /* buffer = CALLOC(I810_DMA_BUF_SZ); */
122 /* if(buffer == NULL) return -1; */
123 /* for(i = 0; i < I810_DMA_BUF_NR; i++) { */
124 /* buf = &(buffers->list[i]); */
125 /* buf->address = (drmAddress)buffer; */
126 /* } */
127 /* return 0; */
128 /* } */
129
130 static drmBufMapPtr i810_create_empty_buffers(void)
131 {
132 drmBufMapPtr retval;
133
134 retval = (drmBufMapPtr)ALIGN_MALLOC(sizeof(drmBufMap), 32);
135 if(retval == NULL) return NULL;
136 memset(retval, 0, sizeof(drmBufMap));
137 retval->list = (drmBufPtr)ALIGN_MALLOC(sizeof(drmBuf) * I810_DMA_BUF_NR, 32);
138 if(retval->list == NULL) {
139 ALIGN_FREE(retval);
140 return NULL;
141 }
142 memset(retval->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
143 return retval;
144 }
145
146
147 static const __DRIconfig **
148 i810InitScreen(__DRIscreen *sPriv)
149 {
150 static const __DRIversion ddx_expected = { 1, 0, 0 };
151 static const __DRIversion dri_expected = { 4, 0, 0 };
152 static const __DRIversion drm_expected = { 1, 2, 0 };
153 i810ScreenPrivate *i810Screen;
154 I810DRIPtr gDRIPriv = (I810DRIPtr)sPriv->pDevPriv;
155
156 if ( ! driCheckDriDdxDrmVersions2( "i810",
157 &sPriv->dri_version, & dri_expected,
158 &sPriv->ddx_version, & ddx_expected,
159 &sPriv->drm_version, & drm_expected ) ) {
160 return NULL;
161 }
162
163 if (sPriv->devPrivSize != sizeof(I810DRIRec)) {
164 fprintf(stderr,"\nERROR! sizeof(I810DRIRec) does not match passed size from device driver\n");
165 return GL_FALSE;
166 }
167
168 /* Allocate the private area */
169 i810Screen = (i810ScreenPrivate *)CALLOC(sizeof(i810ScreenPrivate));
170 if (!i810Screen) {
171 __driUtilMessage("i810InitDriver: alloc i810ScreenPrivate struct failed");
172 return GL_FALSE;
173 }
174
175 i810Screen->driScrnPriv = sPriv;
176 sPriv->private = (void *)i810Screen;
177
178 i810Screen->deviceID=gDRIPriv->deviceID;
179 i810Screen->width=gDRIPriv->width;
180 i810Screen->height=gDRIPriv->height;
181 i810Screen->mem=gDRIPriv->mem;
182 i810Screen->cpp=gDRIPriv->cpp;
183 i810Screen->fbStride=gDRIPriv->fbStride;
184 i810Screen->fbOffset=gDRIPriv->fbOffset;
185
186 if (gDRIPriv->bitsPerPixel == 15)
187 i810Screen->fbFormat = DV_PF_555;
188 else
189 i810Screen->fbFormat = DV_PF_565;
190
191 i810Screen->backOffset=gDRIPriv->backOffset;
192 i810Screen->depthOffset=gDRIPriv->depthOffset;
193 i810Screen->backPitch = gDRIPriv->auxPitch;
194 i810Screen->backPitchBits = gDRIPriv->auxPitchBits;
195 i810Screen->textureOffset=gDRIPriv->textureOffset;
196 i810Screen->textureSize=gDRIPriv->textureSize;
197 i810Screen->logTextureGranularity = gDRIPriv->logTextureGranularity;
198
199 i810Screen->bufs = i810_create_empty_buffers();
200 if (i810Screen->bufs == NULL) {
201 __driUtilMessage("i810InitDriver: i810_create_empty_buffers() failed");
202 FREE(i810Screen);
203 return GL_FALSE;
204 }
205
206 i810Screen->back.handle = gDRIPriv->backbuffer;
207 i810Screen->back.size = gDRIPriv->backbufferSize;
208
209 if (drmMap(sPriv->fd,
210 i810Screen->back.handle,
211 i810Screen->back.size,
212 (drmAddress *)&i810Screen->back.map) != 0) {
213 FREE(i810Screen);
214 sPriv->private = NULL;
215 __driUtilMessage("i810InitDriver: drmMap failed");
216 return GL_FALSE;
217 }
218
219 i810Screen->depth.handle = gDRIPriv->depthbuffer;
220 i810Screen->depth.size = gDRIPriv->depthbufferSize;
221
222 if (drmMap(sPriv->fd,
223 i810Screen->depth.handle,
224 i810Screen->depth.size,
225 (drmAddress *)&i810Screen->depth.map) != 0) {
226 drmUnmap(i810Screen->back.map, i810Screen->back.size);
227 FREE(i810Screen);
228 sPriv->private = NULL;
229 __driUtilMessage("i810InitDriver: drmMap (2) failed");
230 return GL_FALSE;
231 }
232
233 i810Screen->tex.handle = gDRIPriv->textures;
234 i810Screen->tex.size = gDRIPriv->textureSize;
235
236 if (drmMap(sPriv->fd,
237 i810Screen->tex.handle,
238 i810Screen->tex.size,
239 (drmAddress *)&i810Screen->tex.map) != 0) {
240 drmUnmap(i810Screen->back.map, i810Screen->back.size);
241 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
242 FREE(i810Screen);
243 sPriv->private = NULL;
244 __driUtilMessage("i810InitDriver: drmMap (3) failed");
245 return GL_FALSE;
246 }
247
248 i810Screen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
249
250 return i810FillInModes(sPriv, 16, 16, 0, 1);
251 }
252
253 static void
254 i810DestroyScreen(__DRIscreen *sPriv)
255 {
256 i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
257
258 /* Need to unmap all the bufs and maps here:
259 */
260 drmUnmap(i810Screen->back.map, i810Screen->back.size);
261 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
262 drmUnmap(i810Screen->tex.map, i810Screen->tex.size);
263
264 FREE(i810Screen);
265 sPriv->private = NULL;
266 }
267
268
269 /**
270 * Create a buffer which corresponds to the window.
271 */
272 static GLboolean
273 i810CreateBuffer( __DRIscreen *driScrnPriv,
274 __DRIdrawable *driDrawPriv,
275 const __GLcontextModes *mesaVis,
276 GLboolean isPixmap )
277 {
278 i810ScreenPrivate *screen = (i810ScreenPrivate *) driScrnPriv->private;
279
280 if (isPixmap) {
281 return GL_FALSE; /* not implemented */
282 }
283 else {
284 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
285
286 {
287 driRenderbuffer *frontRb
288 = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
289 driScrnPriv->pFB,
290 screen->cpp,
291 /*screen->frontOffset*/0, screen->backPitch,
292 driDrawPriv);
293 i810SetSpanFunctions(frontRb, mesaVis);
294 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
295 }
296
297 if (mesaVis->doubleBufferMode) {
298 driRenderbuffer *backRb
299 = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
300 screen->back.map,
301 screen->cpp,
302 screen->backOffset, screen->backPitch,
303 driDrawPriv);
304 i810SetSpanFunctions(backRb, mesaVis);
305 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
306 }
307
308 if (mesaVis->depthBits == 16) {
309 driRenderbuffer *depthRb
310 = driNewRenderbuffer(MESA_FORMAT_Z16,
311 screen->depth.map,
312 screen->cpp,
313 screen->depthOffset, screen->backPitch,
314 driDrawPriv);
315 i810SetSpanFunctions(depthRb, mesaVis);
316 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
317 }
318
319 _mesa_add_soft_renderbuffers(fb,
320 GL_FALSE, /* color */
321 GL_FALSE, /* depth */
322 mesaVis->stencilBits > 0,
323 mesaVis->accumRedBits > 0,
324 GL_FALSE, /* alpha */
325 GL_FALSE /* aux */);
326 driDrawPriv->driverPrivate = (void *) fb;
327
328 return (driDrawPriv->driverPrivate != NULL);
329 }
330 }
331
332
333 static void
334 i810DestroyBuffer(__DRIdrawable *driDrawPriv)
335 {
336 _mesa_reference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
337 }
338
339 const struct __DriverAPIRec driDriverAPI = {
340 .InitScreen = i810InitScreen,
341 .DestroyScreen = i810DestroyScreen,
342 .CreateContext = i810CreateContext,
343 .DestroyContext = i810DestroyContext,
344 .CreateBuffer = i810CreateBuffer,
345 .DestroyBuffer = i810DestroyBuffer,
346 .SwapBuffers = i810SwapBuffers,
347 .MakeCurrent = i810MakeCurrent,
348 .UnbindContext = i810UnbindContext,
349 .GetSwapInfo = NULL,
350 .GetDrawableMSC = NULL,
351 .WaitForMSC = NULL,
352 .WaitForSBC = NULL,
353 .SwapBuffersMSC = NULL
354 };
355
356 /* This is the table of extensions that the loader will dlsym() for. */
357 PUBLIC const __DRIextension *__driDriverExtensions[] = {
358 &driCoreExtension.base,
359 &driLegacyExtension.base,
360 NULL
361 };