1 /**************************************************************************
3 Copyright 2006 Stephane Marchesin
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 on the rights to use, copy, modify, merge, publish, distribute, sub
10 license, and/or sell copies of the Software, and to permit persons to whom
11 the Software is furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice (including the next
14 paragraph) shall be included in all copies or substantial portions of the
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
21 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
30 #include "framebuffer.h"
31 #include "renderbuffer.h"
33 #include "nouveau_context.h"
34 #include "nouveau_screen.h"
35 #include "nouveau_object.h"
36 #include "nouveau_span.h"
41 #include "drirenderbuffer.h"
43 #include "GL/internal/dri_interface.h"
47 PUBLIC
const char __driConfigOptions
[] =
49 DRI_CONF_SECTION_DEBUG
50 DRI_CONF_NO_RAST(false)
53 static const GLuint __driNConfigOptions
= 1;
55 extern const struct dri_extension common_extensions
[];
56 extern const struct dri_extension nv10_extensions
[];
57 extern const struct dri_extension nv20_extensions
[];
58 extern const struct dri_extension nv30_extensions
[];
59 extern const struct dri_extension nv40_extensions
[];
60 extern const struct dri_extension nv50_extensions
[];
62 static nouveauScreenPtr
nouveauCreateScreen(__DRIscreenPrivate
*sPriv
)
64 nouveauScreenPtr screen
;
65 NOUVEAUDRIPtr dri_priv
=(NOUVEAUDRIPtr
)sPriv
->pDevPriv
;
68 screen
= (nouveauScreenPtr
) CALLOC( sizeof(*screen
) );
70 __driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__
);
74 /* parse information in __driConfigOptions */
75 driParseOptionInfo (&screen
->optionCache
,__driConfigOptions
, __driNConfigOptions
);
77 screen
->fbFormat
= dri_priv
->bpp
/ 8;
78 screen
->frontOffset
= dri_priv
->front_offset
;
79 screen
->frontPitch
= dri_priv
->front_pitch
;
80 screen
->backOffset
= dri_priv
->back_offset
;
81 screen
->backPitch
= dri_priv
->back_pitch
;
82 screen
->depthOffset
= dri_priv
->depth_offset
;
83 screen
->depthPitch
= dri_priv
->depth_pitch
;
85 screen
->card
=nouveau_card_lookup(dri_priv
->device_id
);
86 screen
->driScreen
= sPriv
;
91 nouveauDestroyScreen(__DRIscreenPrivate
*sPriv
)
93 nouveauScreenPtr screen
= (nouveauScreenPtr
)sPriv
->private;
97 /* free all option information */
98 driDestroyOptionInfo (&screen
->optionCache
);
101 sPriv
->private = NULL
;
104 static GLboolean
nouveauInitDriver(__DRIscreenPrivate
*sPriv
)
106 sPriv
->private = (void *) nouveauCreateScreen( sPriv
);
107 if ( !sPriv
->private ) {
108 nouveauDestroyScreen( sPriv
);
116 * Create the Mesa framebuffer and renderbuffers for a given window/drawable.
118 * \todo This function (and its interface) will need to be updated to support
122 nouveauCreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
123 __DRIdrawablePrivate
*driDrawPriv
,
124 const __GLcontextModes
*mesaVis
,
127 nouveauScreenPtr screen
= (nouveauScreenPtr
) driScrnPriv
->private;
128 nouveau_renderbuffer
*nrb
;
129 struct gl_framebuffer
*fb
;
130 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
131 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 && mesaVis
->depthBits
!= 24;
132 GLenum color_format
= screen
->fbFormat
== 4 ? GL_RGBA8
: GL_RGB5
;
135 return GL_FALSE
; /* not implemented */
137 fb
= _mesa_create_framebuffer(mesaVis
);
142 nrb
= nouveau_renderbuffer_new(color_format
,
143 driScrnPriv
->pFB
+ screen
->frontOffset
,
145 screen
->frontPitch
* screen
->fbFormat
,
147 nouveauSpanSetFunctions(nrb
, mesaVis
);
148 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &nrb
->mesa
);
150 if (0 /* unified buffers if we choose to support them.. */) {
152 if (mesaVis
->doubleBufferMode
) {
153 nrb
= nouveau_renderbuffer_new(color_format
, NULL
,
156 nouveauSpanSetFunctions(nrb
, mesaVis
);
157 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &nrb
->mesa
);
160 if (mesaVis
->depthBits
== 24 && mesaVis
->stencilBits
== 8) {
161 nrb
= nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT
, NULL
,
164 nouveauSpanSetFunctions(nrb
, mesaVis
);
165 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &nrb
->mesa
);
166 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &nrb
->mesa
);
167 } else if (mesaVis
->depthBits
== 24) {
168 nrb
= nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24
, NULL
,
171 nouveauSpanSetFunctions(nrb
, mesaVis
);
172 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &nrb
->mesa
);
173 } else if (mesaVis
->depthBits
== 16) {
174 nrb
= nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16
, NULL
,
177 nouveauSpanSetFunctions(nrb
, mesaVis
);
178 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &nrb
->mesa
);
182 _mesa_add_soft_renderbuffers(fb
,
183 GL_FALSE
, /* color */
184 GL_FALSE
, /* depth */
187 GL_FALSE
, /* alpha */
190 driDrawPriv
->driverPrivate
= (void *) fb
;
191 return (driDrawPriv
->driverPrivate
!= NULL
);
196 nouveauDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
198 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
202 nouveauGetSwapInfo(__DRIdrawablePrivate
*dpriv
, __DRIswapInfo
*sInfo
)
207 static const struct __DriverAPIRec nouveauAPI
= {
208 .InitDriver
= nouveauInitDriver
,
209 .DestroyScreen
= nouveauDestroyScreen
,
210 .CreateContext
= nouveauCreateContext
,
211 .DestroyContext
= nouveauDestroyContext
,
212 .CreateBuffer
= nouveauCreateBuffer
,
213 .DestroyBuffer
= nouveauDestroyBuffer
,
214 .SwapBuffers
= nouveauSwapBuffers
,
215 .MakeCurrent
= nouveauMakeCurrent
,
216 .UnbindContext
= nouveauUnbindContext
,
217 .GetSwapInfo
= nouveauGetSwapInfo
,
218 .GetMSC
= driGetMSC32
,
219 .WaitForMSC
= driWaitForMSC32
,
221 .SwapBuffersMSC
= NULL
,
222 .CopySubBuffer
= nouveauCopySubBuffer
226 static __GLcontextModes
*
227 nouveauFillInModes( unsigned pixel_bits
, unsigned depth_bits
,
228 unsigned stencil_bits
, GLboolean have_back_buffer
)
230 __GLcontextModes
* modes
;
231 __GLcontextModes
* m
;
233 unsigned depth_buffer_factor
;
234 unsigned back_buffer_factor
;
237 static const struct {
240 } fb_format_array
[] = {
241 { GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
},
242 { GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
},
243 { GL_BGR
, GL_UNSIGNED_INT_8_8_8_8_REV
},
246 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
247 * support pageflipping at all.
249 static const GLenum back_buffer_modes
[] = {
250 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
253 u_int8_t depth_bits_array
[4] = { 0, 16, 24, 24 };
254 u_int8_t stencil_bits_array
[4] = { 0, 0, 0, 8 };
256 depth_buffer_factor
= 4;
257 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
259 num_modes
= ((pixel_bits
==16) ? 1 : 2) *
260 depth_buffer_factor
* back_buffer_factor
* 4;
261 modes
= (*dri_interface
->createContextModes
)(num_modes
,
262 sizeof(__GLcontextModes
));
265 for (i
=((pixel_bits
==16)?0:1);i
<((pixel_bits
==16)?1:3);i
++) {
266 if (!driFillInModes(&m
, fb_format_array
[i
].format
,
267 fb_format_array
[i
].type
,
274 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
275 __func__
, __LINE__
);
279 if (!driFillInModes(&m
, fb_format_array
[i
].format
,
280 fb_format_array
[i
].type
,
287 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
288 __func__
, __LINE__
);
298 * This is the bootstrap function for the driver. libGL supplies all of the
299 * requisite information about the system, and the driver initializes itself.
300 * This routine also fills in the linked list pointed to by \c driver_modes
301 * with the \c __GLcontextModes that the driver can support for windows or
304 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
308 void * __driCreateNewScreen_20050727( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
309 const __GLcontextModes
* modes
,
310 const __DRIversion
* ddx_version
,
311 const __DRIversion
* dri_version
,
312 const __DRIversion
* drm_version
,
313 const __DRIframebuffer
* frame_buffer
,
314 drmAddress pSAREA
, int fd
,
315 int internal_api_version
,
316 const __DRIinterfaceMethods
* interface
,
317 __GLcontextModes
** driver_modes
)
320 __DRIscreenPrivate
*psp
;
321 static const __DRIversion ddx_expected
= { 1, 2, 0 };
322 static const __DRIversion dri_expected
= { 4, 0, 0 };
323 static const __DRIversion drm_expected
= { 0, 0, 2 };
325 dri_interface
= interface
;
327 if (!driCheckDriDdxDrmVersions2("nouveau",
328 dri_version
, & dri_expected
,
329 ddx_version
, & ddx_expected
,
330 drm_version
, & drm_expected
)) {
334 // temporary lock step versioning
335 if (drm_expected
.patch
!=drm_version
->patch
)
338 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
339 ddx_version
, dri_version
, drm_version
,
340 frame_buffer
, pSAREA
, fd
,
341 internal_api_version
, &nouveauAPI
);
343 NOUVEAUDRIPtr dri_priv
= (NOUVEAUDRIPtr
)psp
->pDevPriv
;
345 *driver_modes
= nouveauFillInModes(dri_priv
->bpp
,
346 (dri_priv
->bpp
== 16) ? 16 : 24,
347 (dri_priv
->bpp
== 16) ? 0 : 8,
351 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
352 * enable the extensions. It just makes sure that all the dispatch offsets for all
353 * the extensions that *might* be enables are known. This is needed because the
354 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
355 * enable the extensions until we have a context pointer.
357 * Hello chicken. Hello egg. How are you two today?
359 driInitExtensions( NULL
, common_extensions
, GL_FALSE
);
360 driInitExtensions( NULL
, nv10_extensions
, GL_FALSE
);
361 driInitExtensions( NULL
, nv10_extensions
, GL_FALSE
);
362 driInitExtensions( NULL
, nv30_extensions
, GL_FALSE
);
363 driInitExtensions( NULL
, nv40_extensions
, GL_FALSE
);
364 driInitExtensions( NULL
, nv50_extensions
, GL_FALSE
);