summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/unichrome/via_texmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/unichrome/via_texmem.c')
-rw-r--r--src/mesa/drivers/dri/unichrome/via_texmem.c499
1 files changed, 499 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/unichrome/via_texmem.c b/src/mesa/drivers/dri/unichrome/via_texmem.c
new file mode 100644
index 0000000000..f1f6b750dd
--- /dev/null
+++ b/src/mesa/drivers/dri/unichrome/via_texmem.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "glheader.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "texformat.h"
+
+#include "mm.h"
+#include "via_context.h"
+#include "via_tex.h"
+#include "via_state.h"
+#include "via_ioctl.h"
+#include "via_fb.h"
+/*=* John Sheng [2003.5.31] agp tex *=*/
+GLuint agpFullCount = 0;
+
+void viaDestroyTexObj(viaContextPtr vmesa, viaTextureObjectPtr t)
+{
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__);
+#endif
+ if (!t)
+ return;
+
+ /* This is sad - need to sync *in case* we upload a texture
+ * to this newly free memory...
+ */
+ if (t->bufAddr) {
+ via_free_texture(vmesa, t);
+
+ if (vmesa && t->age > vmesa->dirtyAge)
+ vmesa->dirtyAge = t->age;
+ }
+
+ if (t->globj)
+ t->globj->DriverData = 0;
+
+ if (vmesa) {
+ if (vmesa->CurrentTexObj[0] == t) {
+ vmesa->CurrentTexObj[0] = 0;
+ vmesa->dirty &= ~VIA_UPLOAD_TEX0;
+ }
+
+ if (vmesa->CurrentTexObj[1] == t) {
+ vmesa->CurrentTexObj[1] = 0;
+ vmesa->dirty &= ~VIA_UPLOAD_TEX1;
+ }
+ }
+
+ remove_from_list(t);
+ free(t);
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);
+#endif
+}
+
+void viaSwapOutTexObj(viaContextPtr vmesa, viaTextureObjectPtr t)
+{
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__);
+#endif
+ if (t->bufAddr) {
+ via_free_texture(vmesa, t);
+
+ if (t->age > vmesa->dirtyAge)
+ vmesa->dirtyAge = t->age;
+ }
+
+ t->dirtyImages = ~0;
+ move_to_tail(&(vmesa->SwappedOut), t);
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);
+#endif
+}
+
+/* Upload an image from mesa's internal copy.
+ */
+static void viaUploadTexLevel(viaTextureObjectPtr t, int level)
+{
+ const struct gl_texture_image *image = t->image[level].image;
+ int i, j;
+#ifdef DEBUG
+ if (VIA_DEBUG) {
+ fprintf(stderr, "%s - in\n", __FUNCTION__);
+ fprintf(stderr, "width = %d, height = %d \n", image->Width, image->Height);
+ }
+#endif
+ switch (t->image[level].internalFormat) {
+ case GL_RGB:
+ {
+ if (image->TexFormat->MesaFormat == MESA_FORMAT_ARGB8888) {
+ GLuint *dst = (GLuint *)(t->bufAddr + t->image[level].offset);
+ GLuint *src = (GLuint *)image->Data;
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "GL_RGB MESA_FORMAT_ARGB8888\n");
+#endif
+ if (image->Width < 8) {
+ for (i = 0; i < image->Height ; i++) {
+ for (j = 0; j < image->Width ; j++) {
+ dst[j] = *src;
+ src++;
+ }
+ dst += 8;
+ }
+ }
+ else {
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ /*memcpy(dst, src, image->Height * image->Width * sizeof(GLuint));*/
+ }
+ else {
+ GLushort *dst = (GLushort *)(t->bufAddr + t->image[level].offset);
+ GLushort *src = (GLushort *)image->Data;
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "GL_RGB !MESA_FORMAT_ARGB8888\n");
+#endif
+ if (image->Width < 16) {
+ for (i = 0; i < image->Height ; i++) {
+ for (j = 0; j < image->Width ; j++) {
+ dst[j] = *src;
+ src++;
+ }
+ dst += 16;
+ }
+ }
+ else {
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ /*memcpy(dst, src, image->Height * image->Width * sizeof(GLushort));*/
+ }
+ }
+ break;
+
+ case GL_RGBA:
+ {
+ if (image->TexFormat->MesaFormat == MESA_FORMAT_ARGB4444) {
+
+ GLushort *dst = (GLushort *)(t->bufAddr + t->image[level].offset);
+ GLushort *src = (GLushort *)image->Data;
+ if (image->Width < 16) {
+ for (i = 0; i < image->Height ; i++) {
+ for (j = 0; j < image->Width ; j++) {
+ dst[j] = *src;
+ src++;
+ }
+ dst += 16;
+ }
+ }
+ else {
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ src++;
+ dst++;
+ }
+ }
+ /*memcpy(dst, src, image->Height * image->Width * sizeof(GLushort));*/
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "GL_RGBA MESA_FORMAT_ARGB4444\n");
+#endif
+ }
+ else if(image->TexFormat->MesaFormat == MESA_FORMAT_ARGB8888) {
+ GLuint *dst = (GLuint *)(t->bufAddr + t->image[level].offset);
+ GLuint *src = (GLuint *)image->Data;
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "GL_RGBA !MESA_FORMAT_ARGB4444\n");
+#endif
+ if (image->Width < 8) {
+ for (i = 0; i < image->Height ; i++) {
+ for (j = 0; j < image->Width ; j++) {
+ dst[j] = *src;
+ src++;
+ }
+ dst += 8;
+ }
+ }
+ else {
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ /*memcpy(dst, src, image->Height * image->Width * sizeof(GLuint));*/
+ }
+ else if(image->TexFormat->MesaFormat == MESA_FORMAT_ARGB1555) {
+ GLushort *dst = (GLushort *)(t->bufAddr + t->image[level].offset);
+ GLushort *src = (GLushort *)image->Data;
+ if (image->Width < 16) {
+ for (i = 0; i < image->Height ; i++) {
+ for (j = 0; j < image->Width ; j++) {
+ dst[j] = *src;
+ src++;
+ }
+ dst += 16;
+ }
+ }
+ else {
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ src++;
+ dst++;
+ }
+ }
+ /*memcpy(dst, src, image->Height * image->Width * sizeof(GLushort));*/
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "GL_RGBA MESA_FORMAT_ARGB1555\n");
+#endif
+ }
+ }
+ break;
+
+ case GL_LUMINANCE:
+ {
+ GLubyte *dst = (GLubyte *)(t->bufAddr + t->image[level].offset);
+ GLubyte *src = (GLubyte *)image->Data;
+
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ break;
+
+ case GL_INTENSITY:
+ {
+ GLubyte *dst = (GLubyte *)(t->bufAddr + t->image[level].offset);
+ GLubyte *src = (GLubyte *)image->Data;
+
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ {
+ GLushort *dst = (GLushort *)(t->bufAddr + t->image[level].offset);
+ GLushort *src = (GLushort *)image->Data;
+
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ break;
+
+ case GL_ALPHA:
+ {
+ GLubyte *dst = (GLubyte *)(t->bufAddr + t->image[level].offset);
+ GLubyte *src = (GLubyte *)image->Data;
+
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ break;
+
+ /* TODO: Translate color indices *now*:
+ */
+ case GL_COLOR_INDEX:
+ {
+ GLubyte *dst = (GLubyte *)(t->bufAddr + t->image[level].offset);
+ GLubyte *src = (GLubyte *)image->Data;
+
+ for (j = 0; j < image->Height * image->Width; j++) {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ break;
+
+ default:;
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "Not supported texture format %s\n",
+ _mesa_lookup_enum_by_nr(image->Format));
+#endif
+ }
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);
+#endif
+}
+
+void viaPrintLocalLRU(viaContextPtr vmesa)
+{
+ viaTextureObjectPtr t;
+
+ foreach (t, &vmesa->TexObjList) {
+ if (!t->globj) {
+#ifdef DEBUG
+ if (VIA_DEBUG) {
+ fprintf(stderr, "offset = %x, index = %x, size = %x\n",
+ t->texMem.offset,
+ t->texMem.index,
+ t->texMem.size);
+ }
+ else {
+ if (VIA_DEBUG) {
+ fprintf(stderr, "offset = %x, siez = %x\n",
+ t->texMem.offset,
+ t->texMem.size);
+ }
+ }
+#endif
+ }
+ }
+}
+
+void viaPrintGlobalLRU(viaContextPtr vmesa)
+{
+ int i, j;
+ drm_via_tex_region_t *list = vmesa->sarea->texList;
+
+ for (i = 0, j = VIA_NR_TEX_REGIONS; i < VIA_NR_TEX_REGIONS; i++) {
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "list[%d] age %d next %d prev %d\n",
+ j, list[j].age, list[j].next, list[j].prev);
+#endif
+ j = list[j].next;
+ if (j == VIA_NR_TEX_REGIONS) break;
+ }
+#ifdef DEBUG
+ if (j != VIA_NR_TEX_REGIONS)
+ if (VIA_DEBUG) fprintf(stderr, "Loop detected in global LRU\n");
+#endif
+}
+
+void viaResetGlobalLRU(viaContextPtr vmesa)
+{
+ drm_via_tex_region_t *list = vmesa->sarea->texList;
+ int sz = 1 << vmesa->viaScreen->logTextureGranularity;
+ int i;
+
+ /* (Re)initialize the global circular LRU list. The last element
+ * in the array (VIA_NR_TEX_REGIONS) is the sentinal. Keeping it
+ * at the end of the array allows it to be addressed rationally
+ * when looking up objects at a particular location in texture
+ * memory.
+ */
+ for (i = 0; (i + 1) * sz <= vmesa->viaScreen->textureSize; i++) {
+ list[i].prev = i - 1;
+ list[i].next = i + 1;
+ list[i].age = 0;
+ }
+
+ i--;
+ list[0].prev = VIA_NR_TEX_REGIONS;
+ list[i].prev = i - 1;
+ list[i].next = VIA_NR_TEX_REGIONS;
+ list[VIA_NR_TEX_REGIONS].prev = i;
+ list[VIA_NR_TEX_REGIONS].next = 0;
+ vmesa->sarea->texAge = 0;
+}
+
+void viaUpdateTexLRU(viaContextPtr vmesa, viaTextureObjectPtr t)
+{
+ vmesa->texAge = ++vmesa->sarea->texAge;
+ move_to_head(&(vmesa->TexObjList), t);
+}
+
+/* Called for every shared texture region which has increased in age
+ * since we last held the lock.
+ *
+ * Figures out which of our textures have been ejected by other clients,
+ * and pushes a placeholder texture onto the LRU list to represent
+ * the other client's textures.
+ */
+void viaTexturesGone(viaContextPtr vmesa,
+ GLuint offset,
+ GLuint size,
+ GLuint inUse)
+{
+ viaTextureObjectPtr t, tmp;
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__);
+#endif
+ foreach_s (t, tmp, &vmesa->TexObjList) {
+ viaSwapOutTexObj(vmesa, t);
+ }
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);
+#endif
+}
+
+/* This is called with the lock held. May have to eject our own and/or
+ * other client's texture objects to make room for the upload.
+ */
+void viaUploadTexImages(viaContextPtr vmesa, viaTextureObjectPtr t)
+{
+ int i, j;
+ int numLevels;
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__);
+#endif
+ LOCK_HARDWARE(vmesa);
+
+ j = 0;
+ if (!t->bufAddr) {
+ while (1) {
+
+ /*=* John Sheng [2003.5.31] agp tex *=*/
+ via_alloc_texture(vmesa, t);
+ /*via_alloc_texture_agp(vmesa, t);*/
+
+ if (t->texMem.offset)
+ break;
+ else
+ agpFullCount++;
+
+ if (vmesa->TexObjList.prev == vmesa->CurrentTexObj[0] ||
+ vmesa->TexObjList.prev == vmesa->CurrentTexObj[1]) {
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "Hit bound texture in upload\n");
+#endif
+ viaPrintLocalLRU(vmesa);
+ UNLOCK_HARDWARE(vmesa);
+ return;
+ }
+
+ if (vmesa->TexObjList.prev == &(vmesa->TexObjList)) {
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
+#endif
+ mmDumpMemInfo(vmesa->texHeap);
+ UNLOCK_HARDWARE(vmesa);
+ return;
+ }
+
+ viaSwapOutTexObj(vmesa, vmesa->TexObjList.prev);
+ }
+ /*=* John Sheng [2003.5.31] agp tex *=*/
+ /*t->bufAddr = (char *)((GLuint)vmesa->driScreen->pFB + t->texMem.offset);*/
+
+ if (t == vmesa->CurrentTexObj[0])
+ VIA_STATECHANGE(vmesa, VIA_UPLOAD_TEX0);
+
+ if (t == vmesa->CurrentTexObj[1])
+ VIA_STATECHANGE(vmesa, VIA_UPLOAD_TEX1);
+
+ viaUpdateTexLRU(vmesa, t);
+
+ j++;
+ }
+
+ numLevels = t->lastLevel - t->firstLevel + 1;
+
+ for (i = 0; i < numLevels; i++)
+ if (t->dirtyImages & (1 << i))
+ viaUploadTexLevel(t, i);
+
+ t->dirtyImages = 0;
+
+ UNLOCK_HARDWARE(vmesa);
+#ifdef DEBUG
+ if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);
+#endif
+}