Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / gallium / winsys / dri / nouveau / nouveau_screen.c
1 #include "utils.h"
2 #include "vblank.h"
3 #include "xmlpool.h"
4
5 #include "pipe/p_context.h"
6 #include "state_tracker/st_public.h"
7 #include "state_tracker/st_cb_fbo.h"
8
9 #include "nouveau_context.h"
10 #include "nouveau_drm.h"
11 #include "nouveau_dri.h"
12 #include "nouveau_local.h"
13 #include "nouveau_screen.h"
14 #include "nouveau_swapbuffers.h"
15
16 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 10
17 #error nouveau_drm.h version does not match expected version
18 #endif
19
20 /* Extension stuff, enabling of extensions handled by Gallium's GL state
21 * tracker. But, we still need to define the entry points we want.
22 */
23 #define need_GL_ARB_fragment_program
24 #define need_GL_ARB_multisample
25 #define need_GL_ARB_occlusion_query
26 #define need_GL_ARB_point_parameters
27 #define need_GL_ARB_shader_objects
28 #define need_GL_ARB_texture_compression
29 #define need_GL_ARB_vertex_program
30 #define need_GL_ARB_vertex_shader
31 #define need_GL_ARB_vertex_buffer_object
32 #define need_GL_EXT_compiled_vertex_array
33 #define need_GL_EXT_fog_coord
34 #define need_GL_EXT_secondary_color
35 #define need_GL_EXT_framebuffer_object
36 #define need_GL_VERSION_2_0
37 #define need_GL_VERSION_2_1
38 #include "extension_helper.h"
39
40 const struct dri_extension card_extensions[] =
41 {
42 { "GL_ARB_multisample", GL_ARB_multisample_functions },
43 { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions },
44 { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
45 { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
46 { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions },
47 { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions },
48 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
49 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
50 { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions },
51 { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
52 { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
53 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
54 { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
55 { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
56 { NULL, 0 }
57 };
58
59 PUBLIC const char __driConfigOptions[] =
60 DRI_CONF_BEGIN
61 DRI_CONF_END;
62 static const GLuint __driNConfigOptions = 0;
63
64 extern const struct dri_extension common_extensions[];
65 extern const struct dri_extension nv40_extensions[];
66
67 static GLboolean
68 nouveau_screen_create(__DRIscreenPrivate *driScrnPriv)
69 {
70 struct nouveau_dri *nv_dri = driScrnPriv->pDevPriv;
71 struct nouveau_screen *nv_screen;
72 int ret;
73
74 if (driScrnPriv->devPrivSize != sizeof(struct nouveau_dri)) {
75 NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n");
76 return GL_FALSE;
77 }
78
79 nv_screen = CALLOC_STRUCT(nouveau_screen);
80 if (!nv_screen)
81 return GL_FALSE;
82 nv_screen->driScrnPriv = driScrnPriv;
83 driScrnPriv->private = (void *)nv_screen;
84
85 driParseOptionInfo(&nv_screen->option_cache,
86 __driConfigOptions, __driNConfigOptions);
87
88 if ((ret = nouveau_device_open_existing(&nv_screen->device, 0,
89 driScrnPriv->fd, 0))) {
90 NOUVEAU_ERR("Failed opening nouveau device: %d\n", ret);
91 return GL_FALSE;
92 }
93
94 nv_screen->front_offset = nv_dri->front_offset;
95 nv_screen->front_pitch = nv_dri->front_pitch * (nv_dri->bpp / 8);
96 nv_screen->front_cpp = nv_dri->bpp / 8;
97 nv_screen->front_height = nv_dri->height;
98
99 return GL_TRUE;
100 }
101
102 static void
103 nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv)
104 {
105 struct nouveau_screen *nv_screen = driScrnPriv->private;
106
107 driScrnPriv->private = NULL;
108 FREE(nv_screen);
109 }
110
111 static GLboolean
112 nouveau_create_buffer(__DRIscreenPrivate * driScrnPriv,
113 __DRIdrawablePrivate * driDrawPriv,
114 const __GLcontextModes *glVis, GLboolean pixmapBuffer)
115 {
116 struct nouveau_framebuffer *nvfb;
117 enum pipe_format colour, depth, stencil;
118
119 if (pixmapBuffer)
120 return GL_FALSE;
121
122 nvfb = CALLOC_STRUCT(nouveau_framebuffer);
123 if (!nvfb)
124 return GL_FALSE;
125
126 if (glVis->redBits == 5)
127 colour = PIPE_FORMAT_R5G6B5_UNORM;
128 else
129 colour = PIPE_FORMAT_A8R8G8B8_UNORM;
130
131 if (glVis->depthBits == 16)
132 depth = PIPE_FORMAT_Z16_UNORM;
133 else if (glVis->depthBits == 24)
134 depth = PIPE_FORMAT_Z24S8_UNORM;
135 else
136 depth = PIPE_FORMAT_NONE;
137
138 if (glVis->stencilBits == 8)
139 stencil = PIPE_FORMAT_Z24S8_UNORM;
140 else
141 stencil = PIPE_FORMAT_NONE;
142
143 nvfb->stfb = st_create_framebuffer(glVis, colour, depth, stencil,
144 driDrawPriv->w, driDrawPriv->h,
145 (void*)nvfb);
146 if (!nvfb->stfb) {
147 free(nvfb);
148 return GL_FALSE;
149 }
150
151 driDrawPriv->driverPrivate = (void *)nvfb;
152 return GL_TRUE;
153 }
154
155 static void
156 nouveau_destroy_buffer(__DRIdrawablePrivate * driDrawPriv)
157 {
158 struct nouveau_framebuffer *nvfb;
159
160 nvfb = (struct nouveau_framebuffer *)driDrawPriv->driverPrivate;
161 st_unreference_framebuffer(&nvfb->stfb);
162 free(nvfb);
163 }
164
165 static struct __DriverAPIRec
166 nouveau_api = {
167 .InitDriver = nouveau_screen_create,
168 .DestroyScreen = nouveau_screen_destroy,
169 .CreateContext = nouveau_context_create,
170 .DestroyContext = nouveau_context_destroy,
171 .CreateBuffer = nouveau_create_buffer,
172 .DestroyBuffer = nouveau_destroy_buffer,
173 .SwapBuffers = nouveau_swap_buffers,
174 .MakeCurrent = nouveau_context_bind,
175 .UnbindContext = nouveau_context_unbind,
176 .GetSwapInfo = NULL,
177 .GetMSC = NULL,
178 .WaitForMSC = NULL,
179 .WaitForSBC = NULL,
180 .SwapBuffersMSC = NULL,
181 .CopySubBuffer = nouveau_copy_sub_buffer,
182 .setTexOffset = NULL
183 };
184
185 static __GLcontextModes *
186 nouveau_fill_in_modes(unsigned pixel_bits, unsigned depth_bits,
187 unsigned stencil_bits, GLboolean have_back_buffer)
188 {
189 __GLcontextModes * modes;
190 __GLcontextModes * m;
191 unsigned num_modes;
192 unsigned depth_buffer_factor;
193 unsigned back_buffer_factor;
194 int i;
195
196 static const struct {
197 GLenum format;
198 GLenum type;
199 } fb_format_array[] = {
200 { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 },
201 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
202 { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
203 };
204
205 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
206 * support pageflipping at all.
207 */
208 static const GLenum back_buffer_modes[] = {
209 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
210 };
211
212 u_int8_t depth_bits_array[4] = { 0, 16, 24, 24 };
213 u_int8_t stencil_bits_array[4] = { 0, 0, 0, 8 };
214
215 depth_buffer_factor = 4;
216 back_buffer_factor = (have_back_buffer) ? 3 : 1;
217
218 num_modes = ((pixel_bits==16) ? 1 : 2) *
219 depth_buffer_factor * back_buffer_factor * 4;
220 modes = (*dri_interface->createContextModes)(num_modes,
221 sizeof(__GLcontextModes));
222 m = modes;
223
224 for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
225 if (!driFillInModes(&m, fb_format_array[i].format,
226 fb_format_array[i].type,
227 depth_bits_array,
228 stencil_bits_array,
229 depth_buffer_factor,
230 back_buffer_modes,
231 back_buffer_factor,
232 GLX_TRUE_COLOR)) {
233 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
234 __func__, __LINE__ );
235 return NULL;
236 }
237
238 if (!driFillInModes(&m, fb_format_array[i].format,
239 fb_format_array[i].type,
240 depth_bits_array,
241 stencil_bits_array,
242 depth_buffer_factor,
243 back_buffer_modes,
244 back_buffer_factor,
245 GLX_DIRECT_COLOR)) {
246 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
247 __func__, __LINE__ );
248 return NULL;
249 }
250 }
251
252 return modes;
253 }
254 PUBLIC void *
255 __driCreateNewScreen_20050727(__DRInativeDisplay *dpy, int scrn,
256 __DRIscreen *psc, const __GLcontextModes * modes,
257 const __DRIversion * ddx_version,
258 const __DRIversion * dri_version,
259 const __DRIversion * drm_version,
260 const __DRIframebuffer * frame_buffer,
261 void * pSAREA, int fd, int internal_api_version,
262 const __DRIinterfaceMethods * interface,
263 __GLcontextModes ** driver_modes)
264 {
265 __DRIscreenPrivate *psp;
266 static const __DRIversion ddx_expected =
267 { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
268 static const __DRIversion dri_expected = { 4, 0, 0 };
269 static const __DRIversion drm_expected =
270 { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
271 struct nouveau_dri *nv_dri = NULL;
272
273 dri_interface = interface;
274
275 if (!driCheckDriDdxDrmVersions2("nouveau",
276 dri_version, &dri_expected,
277 ddx_version, &ddx_expected,
278 drm_version, &drm_expected)) {
279 return NULL;
280 }
281
282 if (drm_expected.patch != drm_version->patch) {
283 fprintf(stderr, "Incompatible DRM patch level.\n"
284 "Expected: %d\n" "Current : %d\n",
285 drm_expected.patch, drm_version->patch);
286 return NULL;
287 }
288
289 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
290 ddx_version, dri_version, drm_version,
291 frame_buffer, pSAREA, fd,
292 internal_api_version,
293 &nouveau_api);
294 if (psp == NULL)
295 return NULL;
296 nv_dri = psp->pDevPriv;
297
298 *driver_modes = nouveau_fill_in_modes(nv_dri->bpp,
299 (nv_dri->bpp == 16) ? 16 : 24,
300 (nv_dri->bpp == 16) ? 0 : 8,
301 1);
302
303 driInitExtensions(NULL, card_extensions, GL_FALSE);
304
305 return (void *)psp;
306 }
307