Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / winsys / r600 / drm / r600_bo.c
1 /*
2  * Copyright 2010 Dave Airlie
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  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * 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 AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *      Dave Airlie
25  */
26 #include <pipe/p_compiler.h>
27 #include <pipe/p_screen.h>
28 #include <pipebuffer/pb_bufmgr.h>
29 #include "state_tracker/drm_driver.h"
30 #include "r600_priv.h"
31 #include "r600d.h"
32 #include "drm.h"
33 #include "radeon_drm.h"
34
35 struct r600_bo *r600_bo(struct radeon *radeon,
36                         unsigned size, unsigned alignment,
37                         unsigned binding, unsigned usage)
38 {
39         struct r600_bo *bo;
40         struct radeon_bo *rbo;
41         uint32_t initial_domain, domains;
42           
43         /* Staging resources particpate in transfers and blits only
44          * and are used for uploads and downloads from regular
45          * resources.  We generate them internally for some transfers.
46          */
47         if (usage == PIPE_USAGE_STAGING)
48                 domains = RADEON_GEM_DOMAIN_CPU | RADEON_GEM_DOMAIN_GTT;
49         else
50                 domains = (RADEON_GEM_DOMAIN_CPU |
51                                 RADEON_GEM_DOMAIN_GTT |
52                                 RADEON_GEM_DOMAIN_VRAM);
53
54         if (binding & (PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) {
55                 bo = r600_bomgr_bo_create(radeon->bomgr, size, alignment, *radeon->cfence);
56                 if (bo) {
57                         bo->domains = domains;
58                         return bo;
59                 }
60         }
61
62         switch(usage) {
63         case PIPE_USAGE_DYNAMIC:
64         case PIPE_USAGE_STREAM:
65         case PIPE_USAGE_STAGING:
66                 initial_domain = RADEON_GEM_DOMAIN_GTT;
67                 break;
68         case PIPE_USAGE_DEFAULT:
69         case PIPE_USAGE_STATIC:
70         case PIPE_USAGE_IMMUTABLE:
71         default:
72                 initial_domain = RADEON_GEM_DOMAIN_VRAM;
73                 break;
74         }
75         rbo = radeon_bo(radeon, 0, size, alignment, initial_domain);
76         if (rbo == NULL) {
77                 return NULL;
78         }
79
80         bo = calloc(1, sizeof(struct r600_bo));
81         bo->size = size;
82         bo->alignment = alignment;
83         bo->domains = domains;
84         bo->bo = rbo;
85         if (binding & (PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)) {
86                 r600_bomgr_bo_init(radeon->bomgr, bo);
87         }
88
89         pipe_reference_init(&bo->reference, 1);
90         return bo;
91 }
92
93 struct r600_bo *r600_bo_handle(struct radeon *radeon,
94                                unsigned handle, unsigned *array_mode)
95 {
96         struct r600_bo *bo = calloc(1, sizeof(struct r600_bo));
97         struct radeon_bo *rbo;
98
99         rbo = bo->bo = radeon_bo(radeon, handle, 0, 0, 0);
100         if (rbo == NULL) {
101                 free(bo);
102                 return NULL;
103         }
104         bo->size = rbo->size;
105         bo->domains = (RADEON_GEM_DOMAIN_CPU |
106                         RADEON_GEM_DOMAIN_GTT |
107                         RADEON_GEM_DOMAIN_VRAM);
108
109         pipe_reference_init(&bo->reference, 1);
110
111         radeon_bo_get_tiling_flags(radeon, rbo, &bo->tiling_flags, &bo->kernel_pitch);
112         if (array_mode) {
113                 if (bo->tiling_flags) {
114                         if (bo->tiling_flags & RADEON_TILING_MACRO)
115                                 *array_mode = V_0280A0_ARRAY_2D_TILED_THIN1;
116                         else if (bo->tiling_flags & RADEON_TILING_MICRO)
117                                 *array_mode = V_0280A0_ARRAY_1D_TILED_THIN1;
118                 } else {
119                         *array_mode = 0;
120                 }
121         }
122         return bo;
123 }
124
125 void *r600_bo_map(struct radeon *radeon, struct r600_bo *bo, unsigned usage, void *ctx)
126 {
127         struct pipe_context *pctx = ctx;
128
129         if (usage & PB_USAGE_UNSYNCHRONIZED) {
130                 radeon_bo_map(radeon, bo->bo);
131                 return (uint8_t *) bo->bo->data + bo->offset;
132         }
133
134         if (p_atomic_read(&bo->bo->reference.count) > 1) {
135                 if (usage & PB_USAGE_DONTBLOCK) {
136                         return NULL;
137                 }
138                 if (ctx) {
139                         pctx->flush(pctx, NULL);
140                 }
141         }
142
143         if (usage & PB_USAGE_DONTBLOCK) {
144                 uint32_t domain;
145
146                 if (radeon_bo_busy(radeon, bo->bo, &domain))
147                         return NULL;
148                 if (radeon_bo_map(radeon, bo->bo)) {
149                         return NULL;
150                 }
151                 goto out;
152         }
153
154         radeon_bo_map(radeon, bo->bo);
155         if (radeon_bo_wait(radeon, bo->bo)) {
156                 radeon_bo_unmap(radeon, bo->bo);
157                 return NULL;
158         }
159
160 out:
161         return (uint8_t *) bo->bo->data + bo->offset;
162 }
163
164 void r600_bo_unmap(struct radeon *radeon, struct r600_bo *bo)
165 {
166         radeon_bo_unmap(radeon, bo->bo);
167 }
168
169 void r600_bo_destroy(struct radeon *radeon, struct r600_bo *bo)
170 {
171         if (bo->manager_id) {
172                 if (!r600_bomgr_bo_destroy(radeon->bomgr, bo)) {
173                         /* destroy is delayed by buffer manager */
174                         return;
175                 }
176         }
177         radeon_bo_reference(radeon, &bo->bo, NULL);
178         free(bo);
179 }
180
181 boolean r600_bo_get_winsys_handle(struct radeon *radeon, struct r600_bo *bo,
182                                 unsigned stride, struct winsys_handle *whandle)
183 {
184         whandle->stride = stride;
185         switch(whandle->type) {
186         case DRM_API_HANDLE_TYPE_KMS:
187                 whandle->handle = bo->bo->handle;
188                 break;
189         case DRM_API_HANDLE_TYPE_SHARED:
190                 if (radeon_bo_get_name(radeon, bo->bo, &whandle->handle))
191                         return FALSE;
192                 break;
193         default:
194                 return FALSE;
195         }
196
197         return TRUE;
198 }