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 #include <errno.h>
25 #include <string.h>
26
27 #include <sys/mman.h>
28
29 #include <drm_fourcc.h>
30
31 #include "xf86drm.h"
32
33 #include "libkms-test.h"
34
kms_framebuffer_create(struct kms_device * device,unsigned int width,unsigned int height,uint32_t format)35 struct kms_framebuffer *kms_framebuffer_create(struct kms_device *device,
36 unsigned int width,
37 unsigned int height,
38 uint32_t format)
39 {
40 uint32_t handles[4], pitches[4], offsets[4];
41 struct drm_mode_create_dumb args;
42 struct kms_framebuffer *fb;
43 int err;
44
45 fb = calloc(1, sizeof(*fb));
46 if (!fb)
47 return NULL;
48
49 fb->device = device;
50 fb->width = width;
51 fb->height = height;
52 fb->format = format;
53
54 memset(&args, 0, sizeof(args));
55 args.width = width;
56 args.height = height;
57
58 switch (format) {
59 case DRM_FORMAT_XRGB8888:
60 case DRM_FORMAT_XBGR8888:
61 case DRM_FORMAT_RGBA8888:
62 args.bpp = 32;
63 break;
64
65 default:
66 free(fb);
67 return NULL;
68 }
69
70 err = drmIoctl(device->fd, DRM_IOCTL_MODE_CREATE_DUMB, &args);
71 if (err < 0) {
72 free(fb);
73 return NULL;
74 }
75
76 fb->handle = args.handle;
77 fb->pitch = args.pitch;
78 fb->size = args.size;
79
80 handles[0] = fb->handle;
81 pitches[0] = fb->pitch;
82 offsets[0] = 0;
83
84 err = drmModeAddFB2(device->fd, width, height, format, handles,
85 pitches, offsets, &fb->id, 0);
86 if (err < 0) {
87 kms_framebuffer_free(fb);
88 return NULL;
89 }
90
91 return fb;
92 }
93
kms_framebuffer_free(struct kms_framebuffer * fb)94 void kms_framebuffer_free(struct kms_framebuffer *fb)
95 {
96 struct kms_device *device = fb->device;
97 struct drm_mode_destroy_dumb args;
98 int err;
99
100 if (fb->id) {
101 err = drmModeRmFB(device->fd, fb->id);
102 if (err < 0) {
103 /* not much we can do now */
104 }
105 }
106
107 memset(&args, 0, sizeof(args));
108 args.handle = fb->handle;
109
110 err = drmIoctl(device->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &args);
111 if (err < 0) {
112 /* not much we can do now */
113 }
114
115 free(fb);
116 }
117
kms_framebuffer_map(struct kms_framebuffer * fb,void ** ptrp)118 int kms_framebuffer_map(struct kms_framebuffer *fb, void **ptrp)
119 {
120 struct kms_device *device = fb->device;
121 struct drm_mode_map_dumb args;
122 void *ptr;
123 int err;
124
125 if (fb->ptr) {
126 *ptrp = fb->ptr;
127 return 0;
128 }
129
130 memset(&args, 0, sizeof(args));
131 args.handle = fb->handle;
132
133 err = drmIoctl(device->fd, DRM_IOCTL_MODE_MAP_DUMB, &args);
134 if (err < 0)
135 return -errno;
136
137 ptr = mmap(0, fb->size, PROT_READ | PROT_WRITE, MAP_SHARED,
138 device->fd, args.offset);
139 if (ptr == MAP_FAILED)
140 return -errno;
141
142 *ptrp = fb->ptr = ptr;
143
144 return 0;
145 }
146
kms_framebuffer_unmap(struct kms_framebuffer * fb)147 void kms_framebuffer_unmap(struct kms_framebuffer *fb)
148 {
149 if (fb->ptr) {
150 munmap(fb->ptr, fb->size);
151 fb->ptr = NULL;
152 }
153 }
154