1bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez/*
2bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * Copyright (C) 2009 Francisco Jerez.
3bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * All Rights Reserved.
4bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez *
5bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * Permission is hereby granted, free of charge, to any person obtaining
6bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * a copy of this software and associated documentation files (the
7bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * "Software"), to deal in the Software without restriction, including
8bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * without limitation the rights to use, copy, modify, merge, publish,
9bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * distribute, sublicense, and/or sell copies of the Software, and to
10bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * permit persons to whom the Software is furnished to do so, subject to
11bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * the following conditions:
12bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez *
13bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * The above copyright notice and this permission notice (including the
14bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * next paragraph) shall be included in all copies or substantial
15bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * portions of the Software.
16bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez *
17bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez *
25bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez */
26bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
27bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez#include "nouveau_driver.h"
28bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez#include "nouveau_bufferobj.h"
29bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez#include "nouveau_context.h"
30bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
31bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez#include "main/bufferobj.h"
32bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
336ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerezstatic inline char *
342e47d01c9e5325906cf3bb979279599991c6328eBen Skeggsget_bufferobj_map(struct gl_context *ctx, struct gl_buffer_object *obj,
352e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		  unsigned flags)
366ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez{
376ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
386ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	void *map = NULL;
396ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez
40f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	if (nbo->sys) {
41f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez		map = nbo->sys;
42f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	} else if (nbo->bo) {
432e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		nouveau_bo_map(nbo->bo, flags, context_client(ctx));
446ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez		map = nbo->bo->map;
456ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	}
466ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez
476ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	return map;
486ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez}
496ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez
50bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic struct gl_buffer_object *
51f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergnouveau_bufferobj_new(struct gl_context *ctx, GLuint buffer, GLenum target)
52bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
53bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_bufferobj *nbo;
54bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
55bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	nbo = CALLOC_STRUCT(nouveau_bufferobj);
56bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	if (!nbo)
57bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		return NULL;
58bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
59f0ea46790f8f4df9a39b0cfab5c5f1bf02c136fcIan Romanick	_mesa_initialize_buffer_object(ctx, &nbo->base, buffer, target);
60bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
61bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	return &nbo->base;
62bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
63bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
64bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
65f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergnouveau_bufferobj_del(struct gl_context *ctx, struct gl_buffer_object *obj)
66bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
67bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
68bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
69bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	nouveau_bo_ref(NULL, &nbo->bo);
70f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	FREE(nbo->sys);
71bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	FREE(nbo);
72bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
73bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
74bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic GLboolean
75f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergnouveau_bufferobj_data(struct gl_context *ctx, GLenum target, GLsizeiptrARB size,
76bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		       const GLvoid *data, GLenum usage,
77bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez		       struct gl_buffer_object *obj)
78bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
79bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj);
80bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	int ret;
81bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
82bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->Size = size;
83bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->Usage = usage;
84bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
85f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	/* Free previous storage */
86bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	nouveau_bo_ref(NULL, &nbo->bo);
87f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	FREE(nbo->sys);
88f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez
89f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	if (target == GL_ELEMENT_ARRAY_BUFFER_ARB ||
90f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	    (size < 512 && usage == GL_DYNAMIC_DRAW_ARB) ||
91f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	    context_chipset(ctx) < 0x10) {
92f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez		/* Heuristic: keep it in system ram */
93f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez		nbo->sys = MALLOC(size);
94f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez
95f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	} else {
96f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez		/* Get a hardware BO */
97f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez		ret = nouveau_bo_new(context_dev(ctx),
98f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez				     NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
992e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs				     size, NULL, &nbo->bo);
100f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez		assert(!ret);
101f67fa5229331f6d4920175dd0d6e1e6a2c69c060Francisco Jerez	}
102bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
1036ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	if (data)
1042e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		memcpy(get_bufferobj_map(ctx, obj, NOUVEAU_BO_WR), data, size);
105bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
106bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	return GL_TRUE;
107bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
108bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
109bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
11092f3fca0ea429dcf07123e63447449db53308266Ian Romanicknouveau_bufferobj_subdata(struct gl_context *ctx, GLintptrARB offset,
111bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			  GLsizeiptrARB size, const GLvoid *data,
112bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			  struct gl_buffer_object *obj)
113bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
1142e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	memcpy(get_bufferobj_map(ctx, obj, NOUVEAU_BO_WR) + offset, data, size);
115bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
116bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
117bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void
1186c8aa3491a19535e8c39a47a3766bf8524e80582Ian Romanicknouveau_bufferobj_get_subdata(struct gl_context *ctx, GLintptrARB offset,
119bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			   GLsizeiptrARB size, GLvoid *data,
120bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			   struct gl_buffer_object *obj)
121bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
1222e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	memcpy(data, get_bufferobj_map(ctx, obj, NOUVEAU_BO_RD) + offset, size);
123bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
124bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
125bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic void *
126681d432f8186cd97e04cf293add72fd73c50523dBrian Paulnouveau_bufferobj_map_range(struct gl_context *ctx, GLintptr offset,
1276ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez			    GLsizeiptr length, GLbitfield access,
128bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez			    struct gl_buffer_object *obj)
129bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
1306ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	unsigned flags = 0;
1316ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	char *map;
132bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
133bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	assert(!obj->Pointer);
134bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
1352e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	if (!(access & GL_MAP_UNSYNCHRONIZED_BIT)) {
1362e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		if (access & GL_MAP_READ_BIT)
1372e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs			flags |= NOUVEAU_BO_RD;
1382e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs		if (access & GL_MAP_WRITE_BIT)
1392e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs			flags |= NOUVEAU_BO_WR;
1402e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	}
141bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
1422e47d01c9e5325906cf3bb979279599991c6328eBen Skeggs	map = get_bufferobj_map(ctx, obj, flags);
1436ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	if (!map)
1446ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez		return NULL;
145bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
1466ee9cd482ab620eb070792ab4176fdc34f945ba7Francisco Jerez	obj->Pointer = map + offset;
147bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->Offset = offset;
148bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->Length = length;
149bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->AccessFlags = access;
150bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
151bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	return obj->Pointer;
152bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
153bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
154bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezstatic GLboolean
15556f0c00f125ee75caeadc1c9e8cab8a488635e5eIan Romanicknouveau_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj)
156bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
157bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	assert(obj->Pointer);
158bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
159bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->Pointer = NULL;
160bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->Offset = 0;
161bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->Length = 0;
162bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	obj->AccessFlags = 0;
163bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
164bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	return GL_TRUE;
165bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
166bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez
167bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerezvoid
168bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jereznouveau_bufferobj_functions_init(struct dd_function_table *functions)
169bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez{
170bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	functions->NewBufferObject = nouveau_bufferobj_new;
171bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	functions->DeleteBuffer	= nouveau_bufferobj_del;
172bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	functions->BufferData = nouveau_bufferobj_data;
173bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	functions->BufferSubData = nouveau_bufferobj_subdata;
174bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	functions->GetBufferSubData = nouveau_bufferobj_get_subdata;
175bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	functions->MapBufferRange = nouveau_bufferobj_map_range;
176bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez	functions->UnmapBuffer = nouveau_bufferobj_unmap;
177bfb5dc68fcc9f5dee71f66d9499b8bdcde9627eaFrancisco Jerez}
178