Merge remote branch 'origin/master' into pipe-video
[mesa.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 *ws_bo = calloc(1, sizeof(struct r600_bo));
40 struct pb_desc desc;
41 struct pb_manager *man;
42
43 desc.alignment = alignment;
44 desc.usage = (PB_USAGE_CPU_READ_WRITE | PB_USAGE_GPU_READ_WRITE);
45 ws_bo->size = size;
46
47 if (binding & (PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
48 man = radeon->cman;
49 else
50 man = radeon->kman;
51
52 /* Staging resources particpate in transfers and blits only
53 * and are used for uploads and downloads from regular
54 * resources. We generate them internally for some transfers.
55 */
56 if (usage == PIPE_USAGE_STAGING)
57 ws_bo->domains = RADEON_GEM_DOMAIN_CPU | RADEON_GEM_DOMAIN_GTT;
58 else
59 ws_bo->domains = (RADEON_GEM_DOMAIN_CPU |
60 RADEON_GEM_DOMAIN_GTT |
61 RADEON_GEM_DOMAIN_VRAM);
62
63
64 ws_bo->pb = man->create_buffer(man, size, &desc);
65 if (ws_bo->pb == NULL) {
66 free(ws_bo);
67 return NULL;
68 }
69
70 pipe_reference_init(&ws_bo->reference, 1);
71 return ws_bo;
72 }
73
74 struct r600_bo *r600_bo_handle(struct radeon *radeon,
75 unsigned handle, unsigned *array_mode)
76 {
77 struct r600_bo *ws_bo = calloc(1, sizeof(struct r600_bo));
78 struct radeon_bo *bo;
79
80 ws_bo->pb = radeon_bo_pb_create_buffer_from_handle(radeon->kman, handle);
81 if (!ws_bo->pb) {
82 free(ws_bo);
83 return NULL;
84 }
85 bo = radeon_bo_pb_get_bo(ws_bo->pb);
86 ws_bo->size = bo->size;
87 ws_bo->domains = (RADEON_GEM_DOMAIN_CPU |
88 RADEON_GEM_DOMAIN_GTT |
89 RADEON_GEM_DOMAIN_VRAM);
90
91 pipe_reference_init(&ws_bo->reference, 1);
92
93 radeon_bo_get_tiling_flags(radeon, bo, &ws_bo->tiling_flags,
94 &ws_bo->kernel_pitch);
95 if (array_mode) {
96 if (ws_bo->tiling_flags) {
97 if (ws_bo->tiling_flags & RADEON_TILING_MICRO)
98 *array_mode = V_0280A0_ARRAY_1D_TILED_THIN1;
99 if ((ws_bo->tiling_flags & (RADEON_TILING_MICRO | RADEON_TILING_MACRO)) ==
100 (RADEON_TILING_MICRO | RADEON_TILING_MACRO))
101 *array_mode = V_0280A0_ARRAY_2D_TILED_THIN1;
102 } else {
103 *array_mode = 0;
104 }
105 }
106 return ws_bo;
107 }
108
109 void *r600_bo_map(struct radeon *radeon, struct r600_bo *bo, unsigned usage, void *ctx)
110 {
111 return pb_map(bo->pb, usage, ctx);
112 }
113
114 void r600_bo_unmap(struct radeon *radeon, struct r600_bo *bo)
115 {
116 pb_unmap(bo->pb);
117 }
118
119 static void r600_bo_destroy(struct radeon *radeon, struct r600_bo *bo)
120 {
121 if (bo->pb)
122 pb_reference(&bo->pb, NULL);
123 free(bo);
124 }
125
126 void r600_bo_reference(struct radeon *radeon, struct r600_bo **dst,
127 struct r600_bo *src)
128 {
129 struct r600_bo *old = *dst;
130
131 if (pipe_reference(&(*dst)->reference, &src->reference)) {
132 r600_bo_destroy(radeon, old);
133 }
134 *dst = src;
135 }
136
137 unsigned r600_bo_get_handle(struct r600_bo *pb_bo)
138 {
139 struct radeon_bo *bo;
140
141 bo = radeon_bo_pb_get_bo(pb_bo->pb);
142 if (!bo)
143 return 0;
144
145 return bo->handle;
146 }
147
148 unsigned r600_bo_get_size(struct r600_bo *pb_bo)
149 {
150 struct radeon_bo *bo;
151
152 bo = radeon_bo_pb_get_bo(pb_bo->pb);
153 if (!bo)
154 return 0;
155
156 return bo->size;
157 }
158
159 boolean r600_bo_get_winsys_handle(struct radeon *radeon, struct r600_bo *pb_bo,
160 unsigned stride, struct winsys_handle *whandle)
161 {
162 struct radeon_bo *bo;
163
164 bo = radeon_bo_pb_get_bo(pb_bo->pb);
165 if (!bo)
166 return FALSE;
167
168 whandle->stride = stride;
169 switch(whandle->type) {
170 case DRM_API_HANDLE_TYPE_KMS:
171 whandle->handle = r600_bo_get_handle(pb_bo);
172 break;
173 case DRM_API_HANDLE_TYPE_SHARED:
174 if (radeon_bo_get_name(radeon, bo, &whandle->handle))
175 return FALSE;
176 break;
177 default:
178 return FALSE;
179 }
180
181 return TRUE;
182 }