nouveau_screen.c revision a4bf68ca50da0ce291a464aec9b03a469ab2561a
1/*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include "nouveau_driver.h"
28#include "nouveau_context.h"
29#include "nouveau_fbo.h"
30#include "nouveau_texture.h"
31#include "nv04_driver.h"
32#include "nv10_driver.h"
33#include "nv20_driver.h"
34
35#include "main/framebuffer.h"
36#include "main/fbobject.h"
37#include "main/renderbuffer.h"
38#include "swrast/s_renderbuffer.h"
39
40static const __DRIextension *nouveau_screen_extensions[];
41
42static void
43nouveau_destroy_screen(__DRIscreen *dri_screen);
44
45static const __DRIconfig **
46nouveau_get_configs(void)
47{
48	__DRIconfig **configs = NULL;
49	int i;
50
51	const uint8_t depth_bits[]   = { 0, 16, 24, 24 };
52	const uint8_t stencil_bits[] = { 0,  0,  0,  8 };
53	const uint8_t msaa_samples[] = { 0 };
54
55	const struct {
56		GLenum format;
57		GLenum type;
58	} fb_formats[] = {
59		{ GL_RGB , GL_UNSIGNED_SHORT_5_6_5     },
60		{ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
61		{ GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
62	};
63
64	const GLenum back_buffer_modes[] = {
65		GLX_NONE, GLX_SWAP_UNDEFINED_OML
66	};
67
68	for (i = 0; i < Elements(fb_formats); i++) {
69		__DRIconfig **config;
70
71		config = driCreateConfigs(fb_formats[i].format,
72					  fb_formats[i].type,
73					  depth_bits, stencil_bits,
74					  Elements(depth_bits),
75					  back_buffer_modes,
76					  Elements(back_buffer_modes),
77					  msaa_samples,
78					  Elements(msaa_samples),
79					  GL_TRUE);
80		assert(config);
81
82		configs = driConcatConfigs(configs, config);
83	}
84
85	return (const __DRIconfig **)configs;
86}
87
88static const __DRIconfig **
89nouveau_init_screen2(__DRIscreen *dri_screen)
90{
91	const __DRIconfig **configs;
92	struct nouveau_screen *screen;
93	int ret;
94
95	/* Allocate the screen. */
96	screen = CALLOC_STRUCT(nouveau_screen);
97	if (!screen)
98		return NULL;
99
100	dri_screen->driverPrivate = screen;
101	dri_screen->extensions = nouveau_screen_extensions;
102	screen->dri_screen = dri_screen;
103
104	/* Open the DRM device. */
105	ret = nouveau_device_wrap(dri_screen->fd, 0, &screen->device);
106	if (ret) {
107		nouveau_error("Error opening the DRM device.\n");
108		goto fail;
109	}
110
111	/* Choose the card specific function pointers. */
112	switch (screen->device->chipset & 0xf0) {
113	case 0x00:
114		screen->driver = &nv04_driver;
115		break;
116	case 0x10:
117		screen->driver = &nv10_driver;
118		break;
119	case 0x20:
120		screen->driver = &nv20_driver;
121		break;
122	default:
123		assert(0);
124	}
125
126	configs = nouveau_get_configs();
127	if (!configs)
128		goto fail;
129
130	return configs;
131fail:
132	nouveau_destroy_screen(dri_screen);
133	return NULL;
134
135}
136
137static void
138nouveau_destroy_screen(__DRIscreen *dri_screen)
139{
140	struct nouveau_screen *screen = dri_screen->driverPrivate;
141
142	if (!screen)
143		return;
144
145	nouveau_device_del(&screen->device);
146
147	FREE(screen);
148	dri_screen->driverPrivate = NULL;
149}
150
151static GLboolean
152nouveau_create_buffer(__DRIscreen *dri_screen,
153		      __DRIdrawable *drawable,
154		      const struct gl_config *visual,
155		      GLboolean is_pixmap)
156{
157	struct gl_renderbuffer *rb;
158	struct gl_framebuffer *fb;
159	GLenum color_format;
160
161	if (is_pixmap)
162		return GL_FALSE; /* not implemented */
163
164	if (visual->redBits == 5)
165		color_format = GL_RGB5;
166	else if (visual->alphaBits == 0)
167		color_format = GL_RGB8;
168	else
169		color_format = GL_RGBA8;
170
171	fb = nouveau_framebuffer_dri_new(visual);
172	if (!fb)
173		return GL_FALSE;
174
175	/* Front buffer. */
176	rb = nouveau_renderbuffer_dri_new(color_format, drawable);
177	_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, rb);
178
179	/* Back buffer */
180	if (visual->doubleBufferMode) {
181		rb = nouveau_renderbuffer_dri_new(color_format, drawable);
182		_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, rb);
183	}
184
185	/* Depth/stencil buffer. */
186	if (visual->depthBits == 24 && visual->stencilBits == 8) {
187		rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable);
188		_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
189		_mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
190
191	} else if (visual->depthBits == 24) {
192		rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable);
193		_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
194
195	} else if (visual->depthBits == 16) {
196		rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable);
197		_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
198	}
199
200	/* Software renderbuffers. */
201	_swrast_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE,
202                                       visual->accumRedBits > 0,
203                                       GL_FALSE, GL_FALSE);
204
205	drawable->driverPrivate = fb;
206
207	return GL_TRUE;
208}
209
210static void
211nouveau_destroy_buffer(__DRIdrawable *drawable)
212{
213	_mesa_reference_framebuffer(
214		(struct gl_framebuffer **)&drawable->driverPrivate, NULL);
215}
216
217static void
218nouveau_drawable_flush(__DRIdrawable *draw)
219{
220}
221
222static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
223    { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
224    nouveau_drawable_flush,
225    dri2InvalidateDrawable,
226};
227
228static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = {
229    { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
230    NULL,
231    nouveau_set_texbuffer,
232};
233
234static const __DRIextension *nouveau_screen_extensions[] = {
235    &nouveau_flush_extension.base,
236    &nouveau_texbuffer_extension.base,
237    &dri2ConfigQueryExtension.base,
238    NULL
239};
240
241const struct __DriverAPIRec driDriverAPI = {
242	.InitScreen      = nouveau_init_screen2,
243	.DestroyScreen   = nouveau_destroy_screen,
244	.CreateBuffer    = nouveau_create_buffer,
245	.DestroyBuffer   = nouveau_destroy_buffer,
246	.CreateContext   = nouveau_context_create,
247	.DestroyContext  = nouveau_context_destroy,
248	.MakeCurrent     = nouveau_context_make_current,
249	.UnbindContext   = nouveau_context_unbind,
250};
251
252/* This is the table of extensions that the loader will dlsym() for. */
253PUBLIC const __DRIextension *__driDriverExtensions[] = {
254	&driCoreExtension.base,
255	&driDRI2Extension.base,
256	NULL
257};
258