nouveau_screen.c revision 7192c37294964b3f6e1551469f161593ec8f851d
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 "nouveau_drmif.h" 32#include "nv04_driver.h" 33#include "nv10_driver.h" 34#include "nv20_driver.h" 35 36#include "main/framebuffer.h" 37#include "main/renderbuffer.h" 38 39static const __DRIextension *nouveau_screen_extensions[]; 40 41static void 42nouveau_destroy_screen(__DRIscreen *dri_screen); 43 44static const __DRIconfig ** 45nouveau_get_configs(void) 46{ 47 __DRIconfig **configs = NULL; 48 int i; 49 50 const uint8_t depth_bits[] = { 0, 16, 24, 24 }; 51 const uint8_t stencil_bits[] = { 0, 0, 0, 8 }; 52 const uint8_t msaa_samples[] = { 0 }; 53 54 const struct { 55 GLenum format; 56 GLenum type; 57 } fb_formats[] = { 58 { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 }, 59 { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, 60 { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV }, 61 }; 62 63 const GLenum back_buffer_modes[] = { 64 GLX_NONE, GLX_SWAP_UNDEFINED_OML 65 }; 66 67 for (i = 0; i < Elements(fb_formats); i++) { 68 __DRIconfig **config; 69 70 config = driCreateConfigs(fb_formats[i].format, 71 fb_formats[i].type, 72 depth_bits, stencil_bits, 73 Elements(depth_bits), 74 back_buffer_modes, 75 Elements(back_buffer_modes), 76 msaa_samples, 77 Elements(msaa_samples), 78 GL_TRUE); 79 assert(config); 80 81 configs = configs ? driConcatConfigs(configs, config) 82 : 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->private = screen; 101 dri_screen->extensions = nouveau_screen_extensions; 102 screen->dri_screen = dri_screen; 103 104 /* Open the DRM device. */ 105 ret = nouveau_device_open_existing(&screen->device, 0, dri_screen->fd, 106 0); 107 if (ret) { 108 nouveau_error("Error opening the DRM device.\n"); 109 goto fail; 110 } 111 112 /* Choose the card specific function pointers. */ 113 switch (screen->device->chipset & 0xf0) { 114 case 0x00: 115 screen->driver = &nv04_driver; 116 break; 117 case 0x10: 118 screen->driver = &nv10_driver; 119 break; 120 case 0x20: 121 screen->driver = &nv20_driver; 122 break; 123 default: 124 assert(0); 125 } 126 127 configs = nouveau_get_configs(); 128 if (!configs) 129 goto fail; 130 131 return configs; 132fail: 133 nouveau_destroy_screen(dri_screen); 134 return NULL; 135 136} 137 138static void 139nouveau_destroy_screen(__DRIscreen *dri_screen) 140{ 141 struct nouveau_screen *screen = dri_screen->private; 142 143 if (!screen) 144 return; 145 146 if (screen->device) 147 nouveau_device_close(&screen->device); 148 149 FREE(screen); 150 dri_screen->private = NULL; 151} 152 153static GLboolean 154nouveau_create_buffer(__DRIscreen *dri_screen, 155 __DRIdrawable *drawable, 156 const struct gl_config *visual, 157 GLboolean is_pixmap) 158{ 159 struct gl_renderbuffer *rb; 160 struct gl_framebuffer *fb; 161 GLenum color_format; 162 163 if (is_pixmap) 164 return GL_FALSE; /* not implemented */ 165 166 if (visual->redBits == 5) 167 color_format = GL_RGB5; 168 else if (visual->alphaBits == 0) 169 color_format = GL_RGB8; 170 else 171 color_format = GL_RGBA8; 172 173 fb = nouveau_framebuffer_dri_new(visual); 174 if (!fb) 175 return GL_FALSE; 176 177 /* Front buffer. */ 178 rb = nouveau_renderbuffer_dri_new(color_format, drawable); 179 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, rb); 180 181 /* Back buffer */ 182 if (visual->doubleBufferMode) { 183 rb = nouveau_renderbuffer_dri_new(color_format, drawable); 184 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, rb); 185 } 186 187 /* Depth/stencil buffer. */ 188 if (visual->depthBits == 24 && visual->stencilBits == 8) { 189 rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable); 190 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 191 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); 192 193 } else if (visual->depthBits == 24) { 194 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable); 195 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 196 197 } else if (visual->depthBits == 16) { 198 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable); 199 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); 200 } 201 202 /* Software renderbuffers. */ 203 _mesa_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE, 204 visual->accumRedBits > 0, 205 GL_FALSE, GL_FALSE); 206 207 drawable->driverPrivate = fb; 208 209 return GL_TRUE; 210} 211 212static void 213nouveau_destroy_buffer(__DRIdrawable *drawable) 214{ 215 _mesa_reference_framebuffer( 216 (struct gl_framebuffer **)&drawable->driverPrivate, NULL); 217} 218 219static void 220nouveau_drawable_flush(__DRIdrawable *draw) 221{ 222} 223 224static const struct __DRI2flushExtensionRec nouveau_flush_extension = { 225 { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, 226 nouveau_drawable_flush, 227 dri2InvalidateDrawable, 228}; 229 230static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = { 231 { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, 232 NULL, 233 nouveau_set_texbuffer, 234}; 235 236static const __DRIextension *nouveau_screen_extensions[] = { 237 &nouveau_flush_extension.base, 238 &nouveau_texbuffer_extension.base, 239 &dri2ConfigQueryExtension.base, 240 NULL 241}; 242 243const struct __DriverAPIRec driDriverAPI = { 244 .InitScreen = nouveau_init_screen2, 245 .DestroyScreen = nouveau_destroy_screen, 246 .CreateBuffer = nouveau_create_buffer, 247 .DestroyBuffer = nouveau_destroy_buffer, 248 .CreateContext = nouveau_context_create, 249 .DestroyContext = nouveau_context_destroy, 250 .MakeCurrent = nouveau_context_make_current, 251 .UnbindContext = nouveau_context_unbind, 252}; 253 254/* This is the table of extensions that the loader will dlsym() for. */ 255PUBLIC const __DRIextension *__driDriverExtensions[] = { 256 &driCoreExtension.base, 257 &driDRI2Extension.base, 258 NULL 259}; 260