1/* 2 * Copyright © 2014 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including 13 * the next paragraph) shall be included in all copies or substantial 14 * portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26#ifndef AMDGPU_PIXMAP_H 27#define AMDGPU_PIXMAP_H 28 29#include "amdgpu_drv.h" 30 31struct amdgpu_pixmap { 32 uint_fast32_t gpu_read; 33 uint_fast32_t gpu_write; 34 35 uint64_t tiling_info; 36 37 struct amdgpu_buffer *bo; 38 struct drmmode_fb *fb; 39 Bool fb_failed; 40 41 /* GEM handle for pixmaps shared via DRI2/3 */ 42 Bool handle_valid; 43 uint32_t handle; 44}; 45 46extern DevPrivateKeyRec amdgpu_pixmap_index; 47 48static inline struct amdgpu_pixmap *amdgpu_get_pixmap_private(PixmapPtr pixmap) 49{ 50 return dixGetPrivate(&pixmap->devPrivates, &amdgpu_pixmap_index); 51} 52 53static inline void amdgpu_set_pixmap_private(PixmapPtr pixmap, 54 struct amdgpu_pixmap *priv) 55{ 56 dixSetPrivate(&pixmap->devPrivates, &amdgpu_pixmap_index, priv); 57} 58 59static inline Bool amdgpu_set_pixmap_bo(PixmapPtr pPix, struct amdgpu_buffer *bo) 60{ 61 ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen); 62 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 63 struct amdgpu_pixmap *priv; 64 65 priv = amdgpu_get_pixmap_private(pPix); 66 if (!priv && !bo) 67 return TRUE; 68 69 if (priv) { 70 if (priv->bo) { 71 if (priv->bo == bo) 72 return TRUE; 73 74 amdgpu_bo_unref(&priv->bo); 75 priv->handle_valid = FALSE; 76 } 77 78 drmmode_fb_reference(pAMDGPUEnt->fd, &priv->fb, NULL); 79 80 if (!bo) { 81 free(priv); 82 priv = NULL; 83 } 84 } 85 86 if (bo) { 87 if (!priv) { 88 priv = calloc(1, sizeof(struct amdgpu_pixmap)); 89 if (!priv) 90 return FALSE; 91 } 92 amdgpu_bo_ref(bo); 93 priv->bo = bo; 94 } 95 96 amdgpu_set_pixmap_private(pPix, priv); 97 return TRUE; 98} 99 100static inline struct amdgpu_buffer *amdgpu_get_pixmap_bo(PixmapPtr pPix) 101{ 102 struct amdgpu_pixmap *priv; 103 priv = amdgpu_get_pixmap_private(pPix); 104 return priv ? priv->bo : NULL; 105} 106 107static inline struct drmmode_fb* 108amdgpu_fb_create(ScrnInfoPtr scrn, int drm_fd, uint32_t width, uint32_t height, 109 uint32_t pitch, uint32_t handle) 110{ 111 struct drmmode_fb *fb = malloc(sizeof(*fb)); 112 113 if (!fb) 114 return NULL; 115 116 fb->refcnt = 1; 117 if (drmModeAddFB(drm_fd, width, height, scrn->depth, scrn->bitsPerPixel, 118 pitch, handle, &fb->handle) == 0) 119 return fb; 120 121 free(fb); 122 return NULL; 123} 124 125static inline struct drmmode_fb** 126amdgpu_pixmap_get_fb_ptr(PixmapPtr pix) 127{ 128 ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen); 129 AMDGPUInfoPtr info = AMDGPUPTR(scrn); 130 131 if (info->use_glamor) { 132 struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pix); 133 134 if (!priv) 135 return NULL; 136 137 return &priv->fb; 138 } 139 140 return NULL; 141} 142 143static inline struct drmmode_fb* 144amdgpu_pixmap_get_fb(PixmapPtr pix) 145{ 146 struct drmmode_fb **fb_ptr = amdgpu_pixmap_get_fb_ptr(pix); 147 uint32_t handle; 148 149 if (fb_ptr && *fb_ptr) 150 return *fb_ptr; 151 152 if (amdgpu_pixmap_get_handle(pix, &handle)) { 153 ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen); 154 AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 155 156 if (!fb_ptr) 157 fb_ptr = amdgpu_pixmap_get_fb_ptr(pix); 158 159 *fb_ptr = amdgpu_fb_create(scrn, pAMDGPUEnt->fd, 160 pix->drawable.width, 161 pix->drawable.height, pix->devKind, 162 handle); 163 } 164 165 return fb_ptr ? *fb_ptr : NULL; 166} 167 168enum { 169 AMDGPU_CREATE_PIXMAP_DRI2 = 0x08000000, 170 AMDGPU_CREATE_PIXMAP_LINEAR = 0x04000000, 171 AMDGPU_CREATE_PIXMAP_SCANOUT = 0x02000000, 172 AMDGPU_CREATE_PIXMAP_GTT = 0x01000000, 173}; 174 175extern Bool amdgpu_pixmap_init(ScreenPtr screen); 176 177#endif /* AMDGPU_PIXMAP_H */ 178