via_memmgr.c revision 963d66ac
1/* 2 * Copyright 2003 Red Hat, Inc. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sub license, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27#include <sys/mman.h> 28 29#include "xf86.h" 30#include "xf86_OSproc.h" 31#include "xf86fbman.h" 32 33#ifdef HAVE_DRI 34#include "xf86drm.h" 35#endif 36 37#include "drm_fourcc.h" 38#include "via_driver.h" 39#ifdef HAVE_DRI 40#include "via_drm.h" 41#else 42#include "drm_fourcc.h" 43#endif 44 45/* 46 * Isolate the wonders of X memory allocation and DRI memory allocation 47 * and 4.3 or 4.4 differences in one abstraction. 48 * 49 * The pool code indicates who provided the memory: 50 * 0 - nobody 51 * 1 - xf86 linear 52 * 2 - DRM 53 */ 54int 55viaOffScreenLinear(struct buffer_object *obj, ScrnInfoPtr pScrn, 56 unsigned long size) 57{ 58 int depth = pScrn->bitsPerPixel >> 3; 59 FBLinearPtr linear; 60 61 linear = xf86AllocateOffscreenLinear(pScrn->pScreen, 62 (size + depth - 1) / depth, 63 32, NULL, NULL, NULL); 64 if (!linear) 65 return BadAlloc; 66 obj->offset = linear->offset * depth; 67 obj->handle = (unsigned long) linear; 68 obj->domain = TTM_PL_FLAG_VRAM; 69 obj->size = size; 70 return Success; 71} 72 73struct buffer_object * 74drm_bo_alloc_surface(ScrnInfoPtr pScrn, unsigned int width, unsigned int height, 75 int format, unsigned int alignment, int domain) 76{ 77 struct buffer_object *obj = NULL; 78 int pitch; 79 80 switch (format) { 81 case DRM_FORMAT_C8: 82 pitch = width; 83 break; 84 85 case DRM_FORMAT_XRGB1555: 86 case DRM_FORMAT_RGB565: 87 pitch = width * 2; 88 break; 89 90 case DRM_FORMAT_RGB888: 91 pitch = width * 3; 92 break; 93 94 case DRM_FORMAT_XRGB2101010: 95 case DRM_FORMAT_XRGB8888: 96 pitch = width * 4; 97 break; 98 } 99 100 pitch = ALIGN_TO(pitch, alignment); 101 obj = drm_bo_alloc(pScrn, pitch * height, alignment, domain); 102 if (!obj->pitch) 103 obj->pitch = pitch; 104 return obj; 105} 106 107struct buffer_object * 108drm_bo_alloc(ScrnInfoPtr pScrn, unsigned int size, unsigned int alignment, int domain) 109{ 110 struct buffer_object *obj = NULL; 111 VIAPtr pVia = VIAPTR(pScrn); 112 int ret = 0; 113 114 obj = xnfcalloc(1, sizeof(*obj)); 115 if (obj) { 116 switch (domain) { 117 case TTM_PL_FLAG_TT: 118 case TTM_PL_FLAG_VRAM: 119 if (pVia->directRenderingType == DRI_NONE) { 120 if (Success != viaOffScreenLinear(obj, pScrn, size)) { 121 ErrorF("Linear memory allocation failed\n"); 122 ret = -ENOMEM; 123 } else 124 DEBUG(ErrorF("%lu bytes of Linear memory allocated at %lx, handle %lu\n", obj->size, obj->offset, obj->handle)); 125#ifdef HAVE_DRI 126 } else if (pVia->directRenderingType == DRI_1) { 127 drm_via_mem_t drm; 128 129 size = ALIGN_TO(size, alignment); 130 drm.context = DRIGetContext(pScrn->pScreen); 131 drm.size = size; 132 drm.type = (domain == TTM_PL_FLAG_TT ? VIA_MEM_AGP : VIA_MEM_VIDEO); 133 ret = drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_ALLOCMEM, 134 &drm, sizeof(drm_via_mem_t)); 135 if (!ret && (size == drm.size)) { 136 if (domain == TTM_PL_FLAG_VRAM) 137 drm.offset -= pVia->FBFreeStart; 138 obj->offset = ALIGN_TO(drm.offset, alignment); 139 obj->handle = drm.index; 140 obj->domain = domain; 141 obj->size = drm.size; 142 DEBUG(ErrorF("%lu bytes of DRI memory allocated at %lx, handle %lu\n", 143 obj->size, obj->offset, obj->handle)); 144 } 145 } else if (pVia->directRenderingType == DRI_2) { 146 struct drm_via_gem_object args; 147 148 /* Some day this will be moved to libdrm. */ 149 args.domains = domain; 150 args.alignment = alignment; 151 args.pitch = 0; 152 args.size = size; 153 ret = drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_GEM_CREATE, 154 &args, sizeof(struct drm_via_gem_object)); 155 if (!ret) { 156 /* Okay the X server expects to know the offset because 157 * of non-KMS. Once we have KMS working the offset 158 * will not be valid. */ 159 obj->map_offset = args.map_handle; 160 obj->offset = args.offset; 161 obj->handle = args.handle; 162 obj->pitch = args.pitch; 163 obj->size = args.size; 164 obj->domain = domain; 165 DEBUG(ErrorF("%lu bytes of DRI2 memory allocated at %lx, handle %lu\n", 166 obj->size, obj->offset, obj->handle)); 167 } 168#endif 169 } 170 break; 171 172 case TTM_PL_FLAG_SYSTEM: 173 default: 174 ret = -ENXIO; 175 break; 176 } 177 178 if (ret) { 179 DEBUG(ErrorF("DRM memory allocation failed %d\n", ret)); 180 free(obj); 181 obj = NULL; 182 }; 183 } 184 return obj; 185} 186 187void* 188drm_bo_map(ScrnInfoPtr pScrn, struct buffer_object *obj) 189{ 190 VIAPtr pVia = VIAPTR(pScrn); 191 192 if (pVia->directRenderingType == DRI_2) { 193 obj->ptr = mmap(0, obj->size, PROT_READ | PROT_WRITE, 194 MAP_SHARED, pVia->drmmode.fd, obj->map_offset); 195 if (obj->ptr == MAP_FAILED) { 196 DEBUG(ErrorF("mmap failed with error %d\n", -errno)); 197 obj->ptr = NULL; 198 } 199 } else { 200 switch (obj->domain) { 201#ifdef HAVE_DRI 202 case TTM_PL_FLAG_TT: 203 obj->ptr = (pVia->agpMappedAddr + obj->offset); 204 break; 205#endif 206 case TTM_PL_FLAG_VRAM: 207 obj->ptr = (pVia->FBBase + obj->offset); 208 break; 209 default: 210 obj->ptr = NULL; 211 break; 212 } 213 } 214 return obj->ptr; 215} 216 217void 218drm_bo_unmap(ScrnInfoPtr pScrn, struct buffer_object *obj) 219{ 220 VIAPtr pVia = VIAPTR(pScrn); 221 222 if (pVia->directRenderingType == DRI_2) 223 munmap(obj->ptr, obj->size); 224 obj->ptr = NULL; 225} 226 227void 228drm_bo_free(ScrnInfoPtr pScrn, struct buffer_object *obj) 229{ 230 VIAPtr pVia = VIAPTR(pScrn); 231 232 if (obj) { 233 DEBUG(ErrorF("Freed %lu (pool %d)\n", obj->offset, obj->domain)); 234 switch (obj->domain) { 235 case TTM_PL_FLAG_VRAM: 236 case TTM_PL_FLAG_TT: 237 if (pVia->directRenderingType == DRI_NONE) { 238 FBLinearPtr linear = (FBLinearPtr) obj->handle; 239 240 xf86FreeOffscreenLinear(linear); 241#ifdef HAVE_DRI 242 } else if (pVia->directRenderingType == DRI_1) { 243 drm_via_mem_t drm; 244 245 drm.index = obj->handle; 246 if (drmCommandWrite(pVia->drmmode.fd, DRM_VIA_FREEMEM, 247 &drm, sizeof(drm_via_mem_t)) < 0) 248 ErrorF("DRM failed to free for handle %lu.\n", obj->handle); 249 } else if (pVia->directRenderingType == DRI_2) { 250 struct drm_gem_close close; 251 252 close.handle = obj->handle; 253 if (drmIoctl(pVia->drmmode.fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) 254 ErrorF("DRM failed to free for handle %lu.\n", obj->handle); 255#endif 256 } 257 break; 258 259 default: 260 break; 261 } 262 free(obj); 263 } 264} 265 266Bool 267drm_bo_manager_init(ScrnInfoPtr pScrn) 268{ 269 VIAPtr pVia = VIAPTR(pScrn); 270 Bool ret = TRUE; 271 272 if (pVia->directRenderingType == DRI_2) 273 return ret; 274 ret = ums_create(pScrn); 275#ifdef HAVE_DRI 276 if (pVia->directRenderingType == DRI_1) 277 ret = VIADRIKernelInit(pScrn); 278#endif 279 return ret; 280} 281