~ubuntu-branches/ubuntu/trusty/mir/trusty-proposed

1.1.55 by Ubuntu daily release
Import upstream version 0.1.4+14.04.20140204
1
/*
2
 * Copyright © 2014 Canonical Ltd.
3
 *
4
 * This program is free software: you can redistribute it and/or modify it
5
 * under the terms of the GNU Lesser General Public License version 3,
6
 * as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 * GNU Lesser General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU Lesser General Public License
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 *
16
 * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
17
 */
18
19
#include "mir_screencast.h"
20
#include "mir/frontend/client_constants.h"
21
#include "mir_toolkit/mir_native_buffer.h"
22
#include "egl_native_window_factory.h"
23
24
#include <boost/throw_exception.hpp>
25
26
namespace mcl = mir::client;
27
namespace geom = mir::geometry;
28
29
namespace
30
{
31
32
void null_callback(MirScreencast*, void*) {}
33
34
geom::Size mir_output_get_size(MirDisplayOutput const& output)
35
{
36
    if (output.connected && output.used &&
37
        output.current_mode < output.num_modes)
38
    {
39
        auto& current_mode = output.modes[output.current_mode];
40
        return geom::Size{current_mode.horizontal_resolution,
41
                          current_mode.vertical_resolution};
42
    }
43
    else
44
    {
45
        BOOST_THROW_EXCEPTION(
46
            std::runtime_error("Couldn't get size from invalid output"));
47
    }
48
}
49
50
51
void populate_buffer_package(
52
    MirBufferPackage& buffer_package,
53
    mir::protobuf::Buffer const& protobuf_buffer)
54
{
55
    if (!protobuf_buffer.has_error())
56
    {
57
        buffer_package.data_items = protobuf_buffer.data_size();
58
        for (int i = 0; i != protobuf_buffer.data_size(); ++i)
59
        {
60
            buffer_package.data[i] = protobuf_buffer.data(i);
61
        }
62
63
        buffer_package.fd_items = protobuf_buffer.fd_size();
64
65
        for (int i = 0; i != protobuf_buffer.fd_size(); ++i)
66
        {
67
            buffer_package.fd[i] = protobuf_buffer.fd(i);
68
        }
69
70
        buffer_package.stride = protobuf_buffer.stride();
71
        buffer_package.flags = protobuf_buffer.flags();
72
        buffer_package.width = protobuf_buffer.width();
73
        buffer_package.height = protobuf_buffer.height();
74
    }
75
    else
76
    {
77
        buffer_package.data_items = 0;
78
        buffer_package.fd_items = 0;
79
        buffer_package.stride = 0;
80
        buffer_package.flags = 0;
81
        buffer_package.width = 0;
82
        buffer_package.height = 0;
83
    }
84
}
85
86
}
87
88
MirScreencast::MirScreencast(
89
    MirDisplayOutput const& output,
90
    mir::protobuf::DisplayServer& server,
91
    std::shared_ptr<mcl::EGLNativeWindowFactory> const& egl_native_window_factory,
92
    std::shared_ptr<mcl::ClientBufferFactory> const& factory,
93
    mir_screencast_callback callback, void* context)
94
    : server(server),
95
      output_id{output.output_id},
96
      output_size{mir_output_get_size(output)},
97
      output_format{output.current_format},
98
      egl_native_window_factory{egl_native_window_factory},
99
      buffer_depository{factory, mir::frontend::client_buffer_cache_size}
100
{
1.1.56 by Ubuntu daily release
Import upstream version 0.1.5+14.04.20140212
101
    protobuf_screencast.set_error("Not initialized");
102
1.1.55 by Ubuntu daily release
Import upstream version 0.1.4+14.04.20140204
103
    mir::protobuf::ScreencastParameters parameters;
104
    parameters.set_output_id(output_id);
105
    parameters.set_width(output_size.width.as_uint32_t());
106
    parameters.set_height(output_size.height.as_uint32_t());
107
108
    server.create_screencast(
109
        nullptr,
110
        &parameters,
111
        &protobuf_screencast,
112
        google::protobuf::NewCallback(
113
            this, &MirScreencast::screencast_created,
114
            callback, context));
115
}
116
117
MirWaitHandle* MirScreencast::creation_wait_handle()
118
{
119
    return &create_screencast_wait_handle;
120
}
121
1.1.56 by Ubuntu daily release
Import upstream version 0.1.5+14.04.20140212
122
bool MirScreencast::valid()
123
{
124
    return !protobuf_screencast.has_error();
125
}
126
1.1.55 by Ubuntu daily release
Import upstream version 0.1.4+14.04.20140204
127
MirSurfaceParameters MirScreencast::get_parameters() const
128
{
129
    return MirSurfaceParameters{
130
        "",
131
        output_size.width.as_int(),
132
        output_size.height.as_int(),
133
        output_format,
134
        mir_buffer_usage_hardware,
135
        output_id};
136
}
137
138
std::shared_ptr<mcl::ClientBuffer> MirScreencast::get_current_buffer()
139
{
140
    return buffer_depository.current_buffer();
141
}
142
143
MirWaitHandle* MirScreencast::release(
144
        mir_screencast_callback callback, void* context)
145
{
146
    mir::protobuf::ScreencastId screencast_id;
147
    screencast_id.set_value(protobuf_screencast.screencast_id().value());
148
149
    server.release_screencast(
150
        nullptr,
151
        &screencast_id,
152
        &protobuf_void,
153
        google::protobuf::NewCallback(
154
            this, &MirScreencast::released, callback, context));
155
156
    return &release_wait_handle;
157
}
158
159
MirWaitHandle* MirScreencast::next_buffer(
160
    mir_screencast_callback callback, void* context)
161
{
162
    mir::protobuf::ScreencastId screencast_id;
163
    screencast_id.set_value(protobuf_screencast.screencast_id().value());
164
165
    server.screencast_buffer(
166
        nullptr,
167
        &screencast_id,
168
        &protobuf_buffer,
169
        google::protobuf::NewCallback(
170
            this, &MirScreencast::next_buffer_received,
171
            callback, context));
172
173
    return &next_buffer_wait_handle;
174
}
175
176
EGLNativeWindowType MirScreencast::egl_native_window()
177
{
178
    return *egl_native_window_;
179
}
180
181
void MirScreencast::request_and_wait_for_next_buffer()
182
{
183
    next_buffer(null_callback, nullptr)->wait_for_all();
184
}
185
186
void MirScreencast::request_and_wait_for_configure(MirSurfaceAttrib, int)
187
{
188
}
189
190
void MirScreencast::process_buffer(mir::protobuf::Buffer const& buffer)
191
{
192
    auto buffer_package = std::make_shared<MirBufferPackage>();
193
    populate_buffer_package(*buffer_package, buffer);
194
195
    try
196
    {
197
        buffer_depository.deposit_package(buffer_package,
1.1.56 by Ubuntu daily release
Import upstream version 0.1.5+14.04.20140212
198
                                          buffer.buffer_id(),
1.1.55 by Ubuntu daily release
Import upstream version 0.1.4+14.04.20140204
199
                                          output_size, output_format);
200
    }
201
    catch (const std::runtime_error& err)
202
    {
203
        // TODO: Report the error
204
    }
205
}
206
207
void MirScreencast::screencast_created(
208
    mir_screencast_callback callback, void* context)
209
{
1.1.56 by Ubuntu daily release
Import upstream version 0.1.5+14.04.20140212
210
    if (!protobuf_screencast.has_error())
211
    {
212
        egl_native_window_ = egl_native_window_factory->create_egl_native_window(this);
213
        process_buffer(protobuf_screencast.buffer());
214
    }
1.1.55 by Ubuntu daily release
Import upstream version 0.1.4+14.04.20140204
215
216
    callback(this, context);
217
    create_screencast_wait_handle.result_received();
218
}
219
220
void MirScreencast::released(
221
    mir_screencast_callback callback, void* context)
222
{
223
    callback(this, context);
224
    release_wait_handle.result_received();
225
}
226
227
void MirScreencast::next_buffer_received(
228
    mir_screencast_callback callback, void* context)
229
{
230
    process_buffer(protobuf_buffer);
231
232
    callback(this, context);
233
    next_buffer_wait_handle.result_received();
234
}