nouveau: Very rough cut at gallium winsys + nv40 pipe driver.
[mesa.git] / src / mesa / drivers / dri / nouveau_winsys / nouveau_screen.c
1 #include "glheader.h"
2 #include "context.h"
3 #include "framebuffer.h"
4 #include "matrix.h"
5 #include "renderbuffer.h"
6 #include "simple_list.h"
7 #include "utils.h"
8 #include "vblank.h"
9 #include "xmlpool.h"
10
11 #include "pipe/p_context.h"
12 #include "state_tracker/st_public.h"
13 #include "state_tracker/st_cb_fbo.h"
14
15 #include "nouveau_context.h"
16 #include "nouveau_device.h"
17 #include "nouveau_drm.h"
18 #include "nouveau_dri.h"
19 #include "nouveau_local.h"
20 #include "nouveau_screen.h"
21 #include "nouveau_swapbuffers.h"
22
23 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 10
24 #error nouveau_drm.h version does not match expected version
25 #endif
26
27 PUBLIC const char __driConfigOptions[] =
28 DRI_CONF_BEGIN
29 DRI_CONF_END;
30 static const GLuint __driNConfigOptions = 0;
31
32 extern const struct dri_extension common_extensions[];
33 extern const struct dri_extension nv40_extensions[];
34
35 static GLboolean
36 nouveau_screen_create(__DRIscreenPrivate *driScrnPriv)
37 {
38 struct nouveau_dri *nv_dri = driScrnPriv->pDevPriv;
39 struct nouveau_screen *nv_screen;
40 int ret;
41
42 if (driScrnPriv->devPrivSize != sizeof(struct nouveau_dri)) {
43 NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n");
44 return GL_FALSE;
45 }
46
47 nv_screen = CALLOC_STRUCT(nouveau_screen);
48 if (!nv_screen)
49 return GL_FALSE;
50 nv_screen->driScrnPriv = driScrnPriv;
51 driScrnPriv->private = (void *)nv_screen;
52
53 driParseOptionInfo(&nv_screen->option_cache,
54 __driConfigOptions, __driNConfigOptions);
55
56 if ((ret = nouveau_device_open_existing(&nv_screen->device, 0,
57 driScrnPriv->fd, 0))) {
58 NOUVEAU_ERR("Failed opening nouveau device: %d\n", ret);
59 return GL_FALSE;
60 }
61
62 nv_screen->front_offset = nv_dri->front_offset;
63 nv_screen->front_pitch = nv_dri->front_pitch * (nv_dri->bpp / 8);
64
65 return GL_TRUE;
66 }
67
68 static void
69 nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv)
70 {
71 struct nouveau_screen *nv_screen = driScrnPriv->private;
72
73 driScrnPriv->private = NULL;
74 FREE(nv_screen);
75 }
76
77 static GLboolean
78 nouveau_create_buffer(__DRIscreenPrivate * driScrnPriv,
79 __DRIdrawablePrivate * driDrawPriv,
80 const __GLcontextModes *glVis, GLboolean pixmapBuffer)
81 {
82 struct nouveau_framebuffer *nvfb;
83
84 if (pixmapBuffer)
85 return GL_FALSE;
86
87 nvfb = CALLOC_STRUCT(nouveau_framebuffer);
88 if (!nvfb)
89 return GL_FALSE;
90
91 nvfb->stfb = st_create_framebuffer(glVis, GL_TRUE, (void*)nvfb);
92 if (!nvfb->stfb) {
93 free(nvfb);
94 return GL_FALSE;
95 }
96
97 driDrawPriv->driverPrivate = (void *)nvfb;
98 return GL_TRUE;
99 }
100
101 static void
102 nouveau_destroy_buffer(__DRIdrawablePrivate * driDrawPriv)
103 {
104 struct nouveau_framebuffer *nvfb;
105
106 nvfb = (struct nouveau_framebuffer *)driDrawPriv;
107 st_unreference_framebuffer(&nvfb->stfb);
108 free(nvfb);
109 }
110
111 static struct __DriverAPIRec
112 nouveau_api = {
113 .InitDriver = nouveau_screen_create,
114 .DestroyScreen = nouveau_screen_destroy,
115 .CreateContext = nouveau_context_create,
116 .DestroyContext = nouveau_context_destroy,
117 .CreateBuffer = nouveau_create_buffer,
118 .DestroyBuffer = nouveau_destroy_buffer,
119 .SwapBuffers = nouveau_swap_buffers,
120 .MakeCurrent = nouveau_context_bind,
121 .UnbindContext = nouveau_context_unbind,
122 .GetSwapInfo = NULL,
123 .GetMSC = NULL,
124 .WaitForMSC = NULL,
125 .WaitForSBC = NULL,
126 .SwapBuffersMSC = NULL,
127 .CopySubBuffer = nouveau_copy_sub_buffer,
128 .setTexOffset = NULL
129 };
130
131 static __GLcontextModes *
132 nouveau_fill_in_modes(unsigned pixel_bits, unsigned depth_bits,
133 unsigned stencil_bits, GLboolean have_back_buffer)
134 {
135 __GLcontextModes * modes;
136 __GLcontextModes * m;
137 unsigned num_modes;
138 unsigned depth_buffer_factor;
139 unsigned back_buffer_factor;
140 int i;
141
142 static const struct {
143 GLenum format;
144 GLenum type;
145 } fb_format_array[] = {
146 { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 },
147 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
148 { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
149 };
150
151 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
152 * support pageflipping at all.
153 */
154 static const GLenum back_buffer_modes[] = {
155 GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
156 };
157
158 u_int8_t depth_bits_array[4] = { 0, 16, 24 };
159 u_int8_t stencil_bits_array[4] = { 0, 0, 8 };
160
161 depth_buffer_factor = 4;
162 back_buffer_factor = (have_back_buffer) ? 3 : 1;
163
164 num_modes = ((pixel_bits==16) ? 1 : 2) *
165 depth_buffer_factor * back_buffer_factor * 4;
166 modes = (*dri_interface->createContextModes)(num_modes,
167 sizeof(__GLcontextModes));
168 m = modes;
169
170 for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
171 if (!driFillInModes(&m, fb_format_array[i].format,
172 fb_format_array[i].type,
173 depth_bits_array,
174 stencil_bits_array,
175 depth_buffer_factor,
176 back_buffer_modes,
177 back_buffer_factor,
178 GLX_TRUE_COLOR)) {
179 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
180 __func__, __LINE__ );
181 return NULL;
182 }
183
184 if (!driFillInModes(&m, fb_format_array[i].format,
185 fb_format_array[i].type,
186 depth_bits_array,
187 stencil_bits_array,
188 depth_buffer_factor,
189 back_buffer_modes,
190 back_buffer_factor,
191 GLX_DIRECT_COLOR)) {
192 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
193 __func__, __LINE__ );
194 return NULL;
195 }
196 }
197
198 return modes;
199 }
200 PUBLIC void *
201 __driCreateNewScreen_20050727(__DRInativeDisplay *dpy, int scrn,
202 __DRIscreen *psc, const __GLcontextModes * modes,
203 const __DRIversion * ddx_version,
204 const __DRIversion * dri_version,
205 const __DRIversion * drm_version,
206 const __DRIframebuffer * frame_buffer,
207 void * pSAREA, int fd, int internal_api_version,
208 const __DRIinterfaceMethods * interface,
209 __GLcontextModes ** driver_modes)
210 {
211 __DRIscreenPrivate *psp;
212 static const __DRIversion ddx_expected = { 1, 2, 0 };
213 static const __DRIversion dri_expected = { 4, 0, 0 };
214 static const __DRIversion drm_expected =
215 { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
216 struct nouveau_dri *nv_dri = NULL;
217
218 dri_interface = interface;
219
220 if (!driCheckDriDdxDrmVersions2("nouveau",
221 dri_version, &dri_expected,
222 ddx_version, &ddx_expected,
223 drm_version, &drm_expected)) {
224 return NULL;
225 }
226
227 if (drm_expected.patch != drm_version->patch) {
228 fprintf(stderr, "Incompatible DRM patch level.\n"
229 "Expected: %d\n" "Current : %d\n",
230 drm_expected.patch, drm_version->patch);
231 return NULL;
232 }
233
234 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
235 ddx_version, dri_version, drm_version,
236 frame_buffer, pSAREA, fd,
237 internal_api_version,
238 &nouveau_api);
239 if (psp == NULL)
240 return NULL;
241 nv_dri = psp->pDevPriv;
242
243 *driver_modes = nouveau_fill_in_modes(nv_dri->bpp,
244 (nv_dri->bpp == 16) ? 16 : 24,
245 (nv_dri->bpp == 16) ? 0 : 8,
246 1);
247
248 driInitExtensions(NULL, common_extensions, GL_FALSE);
249 driInitExtensions(NULL, nv40_extensions, GL_FALSE);
250
251 return (void *)psp;
252 }
253