• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2014 NVIDIA Corporation
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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <errno.h>
29 #include <string.h>
30 
31 #include <sys/mman.h>
32 
33 #include <drm_fourcc.h>
34 
35 #include "xf86drm.h"
36 
37 #include "libkms-test.h"
38 
kms_framebuffer_create(struct kms_device * device,unsigned int width,unsigned int height,uint32_t format)39 struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device,
40 					       unsigned int width,
41 					       unsigned int height,
42 					       uint32_t format)
43 {
44 	uint32_t handles[4], pitches[4], offsets[4];
45 	struct drm_mode_create_dumb args;
46 	struct kms_framebuffer *fb;
47 	int err;
48 
49 	fb = calloc(1, sizeof(*fb));
50 	if (!fb)
51 		return NULL;
52 
53 	fb->device = device;
54 	fb->width = width;
55 	fb->height = height;
56 	fb->format = format;
57 
58 	memset(&args, 0, sizeof(args));
59 	args.width = width;
60 	args.height = height;
61 
62 	switch (format) {
63 	case DRM_FORMAT_XRGB8888:
64 	case DRM_FORMAT_XBGR8888:
65 	case DRM_FORMAT_RGBA8888:
66 		args.bpp = 32;
67 		break;
68 
69 	default:
70 		free(fb);
71 		return NULL;
72 	}
73 
74 	err = drmIoctl(device->fd, DRM_IOCTL_MODE_CREATE_DUMB, &args);
75 	if (err < 0) {
76 		free(fb);
77 		return NULL;
78 	}
79 
80 	fb->handle = args.handle;
81 	fb->pitch = args.pitch;
82 	fb->size = args.size;
83 
84 	handles[0] = fb->handle;
85 	pitches[0] = fb->pitch;
86 	offsets[0] = 0;
87 
88 	err = drmModeAddFB2(device->fd, width, height, format, handles,
89 			    pitches, offsets, &fb->id, 0);
90 	if (err < 0) {
91 		kms_framebuffer_free(fb);
92 		return NULL;
93 	}
94 
95 	return fb;
96 }
97 
kms_framebuffer_free(struct kms_framebuffer * fb)98 void kms_framebuffer_free(struct kms_framebuffer *fb)
99 {
100 	struct kms_device *device = fb->device;
101 	struct drm_mode_destroy_dumb args;
102 	int err;
103 
104 	if (fb->id) {
105 		err = drmModeRmFB(device->fd, fb->id);
106 		if (err < 0) {
107 			/* not much we can do now */
108 		}
109 	}
110 
111 	memset(&args, 0, sizeof(args));
112 	args.handle = fb->handle;
113 
114 	err = drmIoctl(device->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &args);
115 	if (err < 0) {
116 		/* not much we can do now */
117 	}
118 
119 	free(fb);
120 }
121 
kms_framebuffer_map(struct kms_framebuffer * fb,void ** ptrp)122 int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp)
123 {
124 	struct kms_device *device = fb->device;
125 	struct drm_mode_map_dumb args;
126 	void *ptr;
127 	int err;
128 
129 	if (fb->ptr) {
130 		*ptrp = fb->ptr;
131 		return 0;
132 	}
133 
134 	memset(&args, 0, sizeof(args));
135 	args.handle = fb->handle;
136 
137 	err = drmIoctl(device->fd, DRM_IOCTL_MODE_MAP_DUMB, &args);
138 	if (err < 0)
139 		return -errno;
140 
141 	ptr = mmap(0, fb->size, PROT_READ | PROT_WRITE, MAP_SHARED,
142 		   device->fd, args.offset);
143 	if (ptr == MAP_FAILED)
144 		return -errno;
145 
146 	*ptrp = fb->ptr = ptr;
147 
148 	return 0;
149 }
150 
kms_framebuffer_unmap(struct kms_framebuffer * fb)151 void kms_framebuffer_unmap(struct kms_framebuffer *fb)
152 {
153 	if (fb->ptr) {
154 		munmap(fb->ptr, fb->size);
155 		fb->ptr = NULL;
156 	}
157 }
158