Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/mesa into pipe-video
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_bufferobj.c
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_bufferobj.h"
29 #include "nouveau_context.h"
30
31 #include "main/bufferobj.h"
32
33 static struct gl_buffer_object *
34 nouveau_bufferobj_new(struct gl_context *ctx, GLuint buffer, GLenum target)
35 {
36 struct nouveau_bufferobj *nbo;
37
38 nbo = CALLOC_STRUCT(nouveau_bufferobj);
39 if (!nbo)
40 return NULL;
41
42 _mesa_initialize_buffer_object(&nbo->base, buffer, target);
43
44 return &nbo->base;
45 }
46
47 static void
48 nouveau_bufferobj_del(struct gl_context *ctx, struct gl_buffer_object *obj)
49 {
50 struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
51
52 nouveau_bo_ref(NULL, &nbo->bo);
53 FREE(nbo);
54 }
55
56 static GLboolean
57 nouveau_bufferobj_data(struct gl_context *ctx, GLenum target, GLsizeiptrARB size,
58 const GLvoid *data, GLenum usage,
59 struct gl_buffer_object *obj)
60 {
61 struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
62 int ret;
63
64 obj->Size = size;
65 obj->Usage = usage;
66
67 nouveau_bo_ref(NULL, &nbo->bo);
68 ret = nouveau_bo_new(context_dev(ctx),
69 NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
70 size, &nbo->bo);
71 assert(!ret);
72
73 if (data) {
74 nouveau_bo_map(nbo->bo, NOUVEAU_BO_WR);
75 memcpy(nbo->bo->map, data, size);
76 nouveau_bo_unmap(nbo->bo);
77 }
78
79 return GL_TRUE;
80 }
81
82 static void
83 nouveau_bufferobj_subdata(struct gl_context *ctx, GLenum target, GLintptrARB offset,
84 GLsizeiptrARB size, const GLvoid *data,
85 struct gl_buffer_object *obj)
86 {
87 struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
88
89 nouveau_bo_map(nbo->bo, NOUVEAU_BO_WR);
90 memcpy(nbo->bo->map + offset, data, size);
91 nouveau_bo_unmap(nbo->bo);
92 }
93
94 static void
95 nouveau_bufferobj_get_subdata(struct gl_context *ctx, GLenum target, GLintptrARB offset,
96 GLsizeiptrARB size, GLvoid *data,
97 struct gl_buffer_object *obj)
98 {
99 struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
100
101 nouveau_bo_map(nbo->bo, NOUVEAU_BO_RD);
102 memcpy(data, nbo->bo->map + offset, size);
103 nouveau_bo_unmap(nbo->bo);
104 }
105
106 static void *
107 nouveau_bufferobj_map(struct gl_context *ctx, GLenum target, GLenum access,
108 struct gl_buffer_object *obj)
109 {
110 return ctx->Driver.MapBufferRange(ctx, target, 0, obj->Size, access,
111 obj);
112 }
113
114 static void *
115 nouveau_bufferobj_map_range(struct gl_context *ctx, GLenum target, GLintptr offset,
116 GLsizeiptr length, GLenum access,
117 struct gl_buffer_object *obj)
118 {
119 struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
120 uint32_t flags = 0;
121
122 assert(!obj->Pointer);
123
124 if (!nbo->bo)
125 return NULL;
126
127 if (access == GL_READ_ONLY_ARB ||
128 access == GL_READ_WRITE_ARB)
129 flags |= NOUVEAU_BO_RD;
130 if (access == GL_WRITE_ONLY_ARB ||
131 access == GL_READ_WRITE_ARB)
132 flags |= NOUVEAU_BO_WR;
133
134 nouveau_bo_map_range(nbo->bo, offset, length, flags);
135
136 obj->Pointer = nbo->bo->map;
137 obj->Offset = offset;
138 obj->Length = length;
139 obj->AccessFlags = access;
140
141 return obj->Pointer;
142 }
143
144 static GLboolean
145 nouveau_bufferobj_unmap(struct gl_context *ctx, GLenum target, struct gl_buffer_object *obj)
146 {
147 struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
148
149 assert(obj->Pointer);
150
151 nouveau_bo_unmap(nbo->bo);
152
153 obj->Pointer = NULL;
154 obj->Offset = 0;
155 obj->Length = 0;
156 obj->AccessFlags = 0;
157
158 return GL_TRUE;
159 }
160
161 void
162 nouveau_bufferobj_functions_init(struct dd_function_table *functions)
163 {
164 functions->NewBufferObject = nouveau_bufferobj_new;
165 functions->DeleteBuffer = nouveau_bufferobj_del;
166 functions->BufferData = nouveau_bufferobj_data;
167 functions->BufferSubData = nouveau_bufferobj_subdata;
168 functions->GetBufferSubData = nouveau_bufferobj_get_subdata;
169 functions->MapBuffer = nouveau_bufferobj_map;
170 functions->MapBufferRange = nouveau_bufferobj_map_range;
171 functions->UnmapBuffer = nouveau_bufferobj_unmap;
172 }