File: texture.c

package info (click to toggle)
s3d 0.2.2.1-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,356 kB
  • sloc: ansic: 21,128; python: 488; perl: 98; makefile: 31; sh: 29
file content (131 lines) | stat: -rw-r--r-- 3,436 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// SPDX-License-Identifier: LGPL-2.1-or-later
/* SPDX-FileCopyrightText: 2007-2015  Simon Wunderlich <sw@simonwunderlich.de>
 */

#include "s3d.h"
#include "s3dlib.h"
#include "hash.h"
#ifdef SHM
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
#include <stdlib.h>  /* malloc(), free() */
#include <errno.h>  /* errno */
#include <string.h>  /* memcpy() */

static int _s3d_compare_cb(const void *d1, const void *d2);
static int _s3d_choose_cb(const void *d1, int size);
static void _s3d_free_s3dtex(void *d1);
static struct hashtable_t *tex_hash = NULL;

static int _s3d_choose_cb(const void *d1, int size)
{
	struct s3d_texshm *t1 = (struct s3d_texshm *)d1;
	return (t1->oid*32 + t1->tex) % size;
}

static int _s3d_compare_cb(const void *d1, const void *d2)
{
	struct s3d_texshm *t1, *t2;
	t1 = (struct s3d_texshm *)d1;
	t2 = (struct s3d_texshm *)d2;
	if ((t1->oid == t2->oid) && (t1->tex == t2->tex))
		return 0;
	return 1;
}

static void _s3d_free_s3dtex(void *d1)
{
	struct s3d_tex *tex = (struct s3d_tex *)d1;
#ifdef SHM
	if (tex->buf != NULL) {
		shmdt(tex->buf);
		tex->buf = NULL;
	}
	shmctl(tex->tshm.shmid, IPC_RMID, NULL);
	free(tex);
#endif
	return;
}

void _s3d_handle_texshm(struct s3d_texshm *tshm)
{
	struct s3d_tex *tex = NULL;
	s3dprintf(HIGH, "handling new texture ...");
	if (tex_hash == NULL)
		return;
#ifdef SHM
	tex = (struct s3d_tex *)_s3d_hash_remove(tex_hash, tshm);
	if (tex != NULL)
		_s3d_free_s3dtex(tex);
	if (tshm->shmid == -1)
		return;

	tex = (struct s3d_tex *)malloc(sizeof(*tex));
	tex->tshm = *tshm;
	tex->buf = (char*)shmat(tex->tshm.shmid, (void *)0, 0);
	if ((key_t *)tex->buf == (key_t *)(-1)) {
		errn("shm_init():shmat()", errno);
		free(tex);
		return;
	}
	s3dprintf(HIGH, "adding new texture ...");
	_s3d_hash_add(tex_hash, tex);
#endif
	return;
}
int _s3d_load_texture_shm(int object, uint32_t tid, uint16_t xpos, uint16_t ypos, uint16_t w, uint16_t h, const uint8_t *data)
{
	struct s3d_texshm check;
	struct s3d_tex *tex;
	int32_t i, p1, p2, m;
	int16_t mw, mh;

	if (tex_hash == NULL)
		return -1;
	check.oid = object;
	check.tex = tid;
	tex = (struct s3d_tex *)_s3d_hash_find(tex_hash, (void *) & check);
	if (tex == NULL)
		return -1; /* coudn't find */
	s3dprintf(VLOW, "texture: oid %d, tex %d, shmid %d, tw %d, th %d, w %d, h %d ...",
	          tex->tshm.oid, tex->tshm.tex, tex->tshm.shmid, tex->tshm.tw, tex->tshm.th, tex->tshm.w, tex->tshm.th);
	/* found it, assume that it's properly attached. */
	m = tex->tshm.w * tex->tshm.th + tex->tshm.tw;     /*  maximum: position of the last pixel in the buffer */
	if ((xpos + w) > tex->tshm.tw) mw = (tex->tshm.tw - xpos);
	else       mw = w;
	if ((ypos + h) > tex->tshm.th) mh = (tex->tshm.th - ypos);
	else       mh = h;

	if (mw <= 0) { /*  nothing to do */
		return 0;
	}
	for (i = 0; i < mh; i++) {
		p1 = (ypos + i) * tex->tshm.w + xpos;  /*  scanline start position */
		p2 = mw;  /*  and length */
		if (p1 > m) {
			break;   /*  need to break here. */
		}
		memcpy(tex->buf + 4*p1,     /*  draw at p1 position ... */
		       data + 4*i*w,   /*  scanline number i ... */
		       4*p2);
	}
	return 0;
}
int _s3d_texture_init(void)
{
	tex_hash = _s3d_hash_new(256, _s3d_compare_cb, _s3d_choose_cb);
	if (tex_hash == NULL)
		return -1;
	else
		return 0;
}
int _s3d_texture_quit(void)
{
	if (tex_hash == NULL)
		return -1;
	_s3d_hash_delete(tex_hash, _s3d_free_s3dtex);
	tex_hash = NULL;
	return 0;
}