re-add MSAA support
[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/fbobject.h"
40 #include "main/matrix.h"
41 #include "main/renderbuffer.h"
42 #include "main/simple_list.h"
43 #include "utils.h"
44
45 #include "i810screen.h"
46 #include "i810_dri.h"
47
48 #include "i810state.h"
49 #include "i810tex.h"
50 #include "i810span.h"
51 #include "i810tris.h"
52 #include "i810ioctl.h"
53
54 #include "GL/internal/dri_interface.h"
55
56 extern const struct dri_extension card_extensions[];
57
58 static const __DRIconfig **
59 i810FillInModes( __DRIscreenPrivate *psp,
60 unsigned pixel_bits, unsigned depth_bits,
61 unsigned stencil_bits, GLboolean have_back_buffer )
62 {
63 __DRIconfig **configs;
64 __GLcontextModes * m;
65 unsigned depth_buffer_factor;
66 unsigned back_buffer_factor;
67 unsigned i;
68
69 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
70 * enough to add support. Basically, if a context is created with an
71 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
72 * will never be used.
73 */
74 static const GLenum back_buffer_modes[] = {
75 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
76 };
77
78 uint8_t depth_bits_array[2];
79 uint8_t stencil_bits_array[2];
80 uint8_t msaa_samples_array[1];
81
82 depth_bits_array[0] = depth_bits;
83 depth_bits_array[1] = depth_bits;
84
85 /* Just like with the accumulation buffer, always provide some modes
86 * with a stencil buffer. It will be a sw fallback, but some apps won't
87 * care about that.
88 */
89 stencil_bits_array[0] = 0;
90 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
91
92 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
93 back_buffer_factor = (have_back_buffer) ? 2 : 1;
94
95 configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
96 depth_bits_array, stencil_bits_array,
97 depth_buffer_factor,
98 back_buffer_modes, back_buffer_factor,
99 msaa_samples_array, 1);
100 if (configs == NULL) {
101 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
102 __func__, __LINE__ );
103 return NULL;
104 }
105
106 /* Mark the visual as slow if there are "fake" stencil bits.
107 */
108 for (i = 0; configs[i]; i++) {
109 m = &configs[i]->modes;
110 if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
111 m->visualRating = GLX_SLOW_CONFIG;
112 }
113 }
114
115 return (const __DRIconfig **) configs;
116 }
117
118
119 /* static int i810_malloc_proxy_buf(drmBufMapPtr buffers) */
120 /* { */
121 /* char *buffer; */
122 /* drmBufPtr buf; */
123 /* int i; */
124
125 /* buffer = CALLOC(I810_DMA_BUF_SZ); */
126 /* if(buffer == NULL) return -1; */
127 /* for(i = 0; i < I810_DMA_BUF_NR; i++) { */
128 /* buf = &(buffers->list[i]); */
129 /* buf->address = (drmAddress)buffer; */
130 /* } */
131 /* return 0; */
132 /* } */
133
134 static drmBufMapPtr i810_create_empty_buffers(void)
135 {
136 drmBufMapPtr retval;
137
138 retval = (drmBufMapPtr)ALIGN_MALLOC(sizeof(drmBufMap), 32);
139 if(retval == NULL) return NULL;
140 memset(retval, 0, sizeof(drmBufMap));
141 retval->list = (drmBufPtr)ALIGN_MALLOC(sizeof(drmBuf) * I810_DMA_BUF_NR, 32);
142 if(retval->list == NULL) {
143 ALIGN_FREE(retval);
144 return NULL;
145 }
146 memset(retval->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
147 return retval;
148 }
149
150
151 static const __DRIconfig **
152 i810InitScreen(__DRIscreen *sPriv)
153 {
154 static const __DRIversion ddx_expected = { 1, 0, 0 };
155 static const __DRIversion dri_expected = { 4, 0, 0 };
156 static const __DRIversion drm_expected = { 1, 2, 0 };
157 i810ScreenPrivate *i810Screen;
158 I810DRIPtr gDRIPriv = (I810DRIPtr)sPriv->pDevPriv;
159
160 if ( ! driCheckDriDdxDrmVersions2( "i810",
161 &sPriv->dri_version, & dri_expected,
162 &sPriv->ddx_version, & ddx_expected,
163 &sPriv->drm_version, & drm_expected ) ) {
164 return NULL;
165 }
166
167 driInitExtensions( NULL, card_extensions, GL_TRUE );
168
169 if (sPriv->devPrivSize != sizeof(I810DRIRec)) {
170 fprintf(stderr,"\nERROR! sizeof(I810DRIRec) does not match passed size from device driver\n");
171 return GL_FALSE;
172 }
173
174 /* Allocate the private area */
175 i810Screen = (i810ScreenPrivate *)CALLOC(sizeof(i810ScreenPrivate));
176 if (!i810Screen) {
177 __driUtilMessage("i810InitDriver: alloc i810ScreenPrivate struct failed");
178 return GL_FALSE;
179 }
180
181 i810Screen->driScrnPriv = sPriv;
182 sPriv->private = (void *)i810Screen;
183
184 i810Screen->deviceID=gDRIPriv->deviceID;
185 i810Screen->width=gDRIPriv->width;
186 i810Screen->height=gDRIPriv->height;
187 i810Screen->mem=gDRIPriv->mem;
188 i810Screen->cpp=gDRIPriv->cpp;
189 i810Screen->fbStride=gDRIPriv->fbStride;
190 i810Screen->fbOffset=gDRIPriv->fbOffset;
191
192 if (gDRIPriv->bitsPerPixel == 15)
193 i810Screen->fbFormat = DV_PF_555;
194 else
195 i810Screen->fbFormat = DV_PF_565;
196
197 i810Screen->backOffset=gDRIPriv->backOffset;
198 i810Screen->depthOffset=gDRIPriv->depthOffset;
199 i810Screen->backPitch = gDRIPriv->auxPitch;
200 i810Screen->backPitchBits = gDRIPriv->auxPitchBits;
201 i810Screen->textureOffset=gDRIPriv->textureOffset;
202 i810Screen->textureSize=gDRIPriv->textureSize;
203 i810Screen->logTextureGranularity = gDRIPriv->logTextureGranularity;
204
205 i810Screen->bufs = i810_create_empty_buffers();
206 if (i810Screen->bufs == NULL) {
207 __driUtilMessage("i810InitDriver: i810_create_empty_buffers() failed");
208 FREE(i810Screen);
209 return GL_FALSE;
210 }
211
212 i810Screen->back.handle = gDRIPriv->backbuffer;
213 i810Screen->back.size = gDRIPriv->backbufferSize;
214
215 if (drmMap(sPriv->fd,
216 i810Screen->back.handle,
217 i810Screen->back.size,
218 (drmAddress *)&i810Screen->back.map) != 0) {
219 FREE(i810Screen);
220 sPriv->private = NULL;
221 __driUtilMessage("i810InitDriver: drmMap failed");
222 return GL_FALSE;
223 }
224
225 i810Screen->depth.handle = gDRIPriv->depthbuffer;
226 i810Screen->depth.size = gDRIPriv->depthbufferSize;
227
228 if (drmMap(sPriv->fd,
229 i810Screen->depth.handle,
230 i810Screen->depth.size,
231 (drmAddress *)&i810Screen->depth.map) != 0) {
232 drmUnmap(i810Screen->back.map, i810Screen->back.size);
233 FREE(i810Screen);
234 sPriv->private = NULL;
235 __driUtilMessage("i810InitDriver: drmMap (2) failed");
236 return GL_FALSE;
237 }
238
239 i810Screen->tex.handle = gDRIPriv->textures;
240 i810Screen->tex.size = gDRIPriv->textureSize;
241
242 if (drmMap(sPriv->fd,
243 i810Screen->tex.handle,
244 i810Screen->tex.size,
245 (drmAddress *)&i810Screen->tex.map) != 0) {
246 drmUnmap(i810Screen->back.map, i810Screen->back.size);
247 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
248 FREE(i810Screen);
249 sPriv->private = NULL;
250 __driUtilMessage("i810InitDriver: drmMap (3) failed");
251 return GL_FALSE;
252 }
253
254 i810Screen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
255
256 return i810FillInModes(sPriv, 16, 16, 0, 1);
257 }
258
259 static void
260 i810DestroyScreen(__DRIscreenPrivate *sPriv)
261 {
262 i810ScreenPrivate *i810Screen = (i810ScreenPrivate *)sPriv->private;
263
264 /* Need to unmap all the bufs and maps here:
265 */
266 drmUnmap(i810Screen->back.map, i810Screen->back.size);
267 drmUnmap(i810Screen->depth.map, i810Screen->depth.size);
268 drmUnmap(i810Screen->tex.map, i810Screen->tex.size);
269
270 FREE(i810Screen);
271 sPriv->private = NULL;
272 }
273
274
275 /**
276 * Create a buffer which corresponds to the window.
277 */
278 static GLboolean
279 i810CreateBuffer( __DRIscreenPrivate *driScrnPriv,
280 __DRIdrawablePrivate *driDrawPriv,
281 const __GLcontextModes *mesaVis,
282 GLboolean isPixmap )
283 {
284 i810ScreenPrivate *screen = (i810ScreenPrivate *) driScrnPriv->private;
285
286 if (isPixmap) {
287 return GL_FALSE; /* not implemented */
288 }
289 else {
290 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
291
292 {
293 driRenderbuffer *frontRb
294 = driNewRenderbuffer(GL_RGBA,
295 driScrnPriv->pFB,
296 screen->cpp,
297 /*screen->frontOffset*/0, screen->backPitch,
298 driDrawPriv);
299 i810SetSpanFunctions(frontRb, mesaVis);
300 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
301 }
302
303 if (mesaVis->doubleBufferMode) {
304 driRenderbuffer *backRb
305 = driNewRenderbuffer(GL_RGBA,
306 screen->back.map,
307 screen->cpp,
308 screen->backOffset, screen->backPitch,
309 driDrawPriv);
310 i810SetSpanFunctions(backRb, mesaVis);
311 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
312 }
313
314 if (mesaVis->depthBits == 16) {
315 driRenderbuffer *depthRb
316 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
317 screen->depth.map,
318 screen->cpp,
319 screen->depthOffset, screen->backPitch,
320 driDrawPriv);
321 i810SetSpanFunctions(depthRb, mesaVis);
322 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
323 }
324
325 _mesa_add_soft_renderbuffers(fb,
326 GL_FALSE, /* color */
327 GL_FALSE, /* depth */
328 mesaVis->stencilBits > 0,
329 mesaVis->accumRedBits > 0,
330 GL_FALSE, /* alpha */
331 GL_FALSE /* aux */);
332 driDrawPriv->driverPrivate = (void *) fb;
333
334 return (driDrawPriv->driverPrivate != NULL);
335 }
336 }
337
338
339 static void
340 i810DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
341 {
342 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
343 }
344
345 const struct __DriverAPIRec driDriverAPI = {
346 .InitScreen = i810InitScreen,
347 .DestroyScreen = i810DestroyScreen,
348 .CreateContext = i810CreateContext,
349 .DestroyContext = i810DestroyContext,
350 .CreateBuffer = i810CreateBuffer,
351 .DestroyBuffer = i810DestroyBuffer,
352 .SwapBuffers = i810SwapBuffers,
353 .MakeCurrent = i810MakeCurrent,
354 .UnbindContext = i810UnbindContext,
355 .GetSwapInfo = NULL,
356 .GetDrawableMSC = NULL,
357 .WaitForMSC = NULL,
358 .WaitForSBC = NULL,
359 .SwapBuffersMSC = NULL
360 };