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
132
133
134
135
136
137
138
|
#include "GraphicsBitmap.h"
#ifdef KERNEL
#include <Kernel/Process.h>
#include <Kernel/MemoryManager.h>
#include <WindowServer/WSMessageLoop.h>
#endif
#ifdef USERLAND
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#endif
#ifdef KERNEL
RetainPtr<GraphicsBitmap> GraphicsBitmap::create_kernel_only(const Size& size)
{
return adopt(*new GraphicsBitmap(size));
}
GraphicsBitmap::GraphicsBitmap(const Size& size)
: m_size(size)
, m_pitch(size.width() * sizeof(RGBA32))
{
InterruptDisabler disabler;
size_t size_in_bytes = size.width() * size.height() * sizeof(RGBA32);
auto vmo = VMObject::create_anonymous(size_in_bytes);
auto& server = WSMessageLoop::the().server_process();
m_server_region = server.allocate_region_with_vmo(LinearAddress(), size_in_bytes, move(vmo), 0, "GraphicsBitmap (server)", true, false);
m_server_region->set_shared(true);
m_server_region->set_is_bitmap(true);
m_data = (RGBA32*)m_server_region->laddr().as_ptr();
}
#endif
RetainPtr<GraphicsBitmap> GraphicsBitmap::create_wrapper(const Size& size, RGBA32* data)
{
return adopt(*new GraphicsBitmap(size, data));
}
RetainPtr<GraphicsBitmap> GraphicsBitmap::load_from_file(const String& path, const Size& size)
{
RGBA32* mapped_data = nullptr;
#ifdef USERLAND
int fd = open(path.characters(), O_RDONLY, 0644);
if (fd < 0) {
dbgprintf("open(%s) got fd=%d, failed: %s\n", path.characters(), fd, strerror(errno));
perror("open");
return nullptr;
}
mapped_data = (RGBA32*)mmap(nullptr, size.area() * 4, PROT_READ, MAP_SHARED, fd, 0);
if (mapped_data == MAP_FAILED) {
int rc = close(fd);
ASSERT(rc == 0);
return nullptr;
}
#else
int error;
auto descriptor = VFS::the().open(path, error, 0, 0, *VFS::the().root_inode());
if (!descriptor) {
kprintf("Failed to load GraphicsBitmap from file (%s)\n", path.characters());
return nullptr;
}
auto* region = WSMessageLoop::the().server_process().allocate_file_backed_region(LinearAddress(), size.area() * 4, descriptor->inode(), ".rgb file", /*readable*/true, /*writable*/false);
mapped_data = (RGBA32*)region->laddr().get();
#endif
#ifdef USERLAND
int rc = close(fd);
ASSERT(rc == 0);
#endif
auto bitmap = create_wrapper(size, mapped_data);
#ifdef KERNEL
bitmap->m_server_region = region;
#else
bitmap->m_mmaped = true;
#endif
return bitmap;
}
GraphicsBitmap::GraphicsBitmap(const Size& size, RGBA32* data)
: m_size(size)
, m_data(data)
, m_pitch(size.width() * sizeof(RGBA32))
{
}
RetainPtr<GraphicsBitmap> GraphicsBitmap::create_with_shared_buffer(int shared_buffer_id, const Size& size, RGBA32* data)
{
if (!data) {
#ifdef KERNEL
void* shared_buffer = current->sys$get_shared_buffer(shared_buffer_id);
#else
void* shared_buffer = get_shared_buffer(shared_buffer_id);
#endif
if (!shared_buffer || shared_buffer == (void*)-1)
return nullptr;
data = (RGBA32*)shared_buffer;
}
return adopt(*new GraphicsBitmap(shared_buffer_id, size, data));
}
GraphicsBitmap::GraphicsBitmap(int shared_buffer_id, const Size& size, RGBA32* data)
: m_size(size)
, m_data(data)
, m_pitch(size.width() * sizeof(RGBA32))
, m_shared_buffer_id(shared_buffer_id)
{
}
GraphicsBitmap::~GraphicsBitmap()
{
#ifdef KERNEL
if (m_server_region)
WSMessageLoop::the().server_process().deallocate_region(*m_server_region);
#else
if (m_mmaped) {
int rc = munmap(m_data, m_size.area() * 4);
ASSERT(rc == 0);
}
#endif
if (m_shared_buffer_id != -1) {
int rc;
#ifdef KERNEL
rc = current->sys$release_shared_buffer(m_shared_buffer_id);
#else
rc = release_shared_buffer(m_shared_buffer_id);
#endif
ASSERT(rc == 0);
}
m_data = nullptr;
}
|