summaryrefslogtreecommitdiffstats
path: root/client/display_channel.h
blob: c56adf6fc3fb261d7654075da93167cf3fd47a3c (plain)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
   Copyright (C) 2009 Red Hat, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _H_DISPLAY_CHANNEL
#define _H_DISPLAY_CHANNEL

#include "common.h"
#include "canvas.h"
#include "region.h"
#include "red_channel.h"
#include "cache.hpp"
#include "screen_layer.h"
#include "process_loop.h"
#ifdef USE_OGL
#include "red_pixmap_gl.h"
#endif
#include "glz_decoder_window.h"

class RedScreen;
class ChannelFactory;
class VideoStream;
class DisplayChannel;
class CursorData;
class InputsChannel;

class StreamsTrigger: public EventSources::Trigger {
public:
    StreamsTrigger(DisplayChannel& channel);

    virtual void on_event();

private:
    DisplayChannel& _channel;
};

#ifdef USE_OGL
class GLInterruptRecreate: public EventSources::Trigger {
public:
    GLInterruptRecreate(DisplayChannel& channel);
    virtual void trigger();
    virtual void on_event();

private:
    DisplayChannel& _channel;
    Mutex _lock;
    Condition _cond;
};
#endif

class InterruptUpdate: public EventSources::Trigger {
public:
    InterruptUpdate(DisplayChannel& channel);

    virtual void on_event();

private:
    DisplayChannel& _channel;
};

class StreamsTimer: public Timer {
public:
    StreamsTimer(DisplayChannel& channel);
    virtual void response(AbstractProcessLoop& events_loop);
private:
    DisplayChannel& _channel;
};

class DisplaySurfacesManger {
public:
    void add_surface(int surface_id, SpiceCanvas *surface);
    void del_surface(int surface_id);
    void add_canvas(int surface_id, Canvas *canvas);
    void del_canvas(int surface_id);

    CSurfaces& get_surfaces();
    bool is_present_canvas(int surface_id);
    Canvas* get_canvas(int surface_id);
private:
    CSurfaces surfaces;
    CCanvases canvases;
};

class DisplayChannel: public RedChannel, public ScreenLayer {
public:
    DisplayChannel(RedClient& client, uint32_t id,
                   PixmapCache& pixmap_cache, GlzDecoderWindow& glz_window);
    virtual ~DisplayChannel();

    virtual void copy_pixels(const QRegion& dest_region, RedDrawable& dest_dc);
    virtual void copy_pixels(const QRegion& dest_region, const PixmapHeader &dest);
#ifdef USE_OGL
    virtual void recreate_ogl_context();
    virtual void recreate_ogl_context_interrupt();
    virtual void pre_migrate();
    virtual void post_migrate();
#endif
    virtual void update_interrupt();
    void set_cursor(CursorData* cursor);
    void hide_cursor();
    void set_capture_mode(bool on);

    virtual bool pointer_test(int x, int y);
    virtual void on_pointer_enter(int x, int y, unsigned int buttons_state);
    virtual void on_pointer_motion(int x, int y, unsigned int buttons_state);
    virtual void on_pointer_leave();
    virtual void on_mouse_button_press(int button, int buttons_state);
    virtual void on_mouse_button_release(int button, int buttons_state);

    void attach_inputs(InputsChannel* inputs_channel);
    void detach_inputs();

    static ChannelFactory& Factory();

protected:
    virtual void on_connect();
    virtual void on_disconnect();

private:
    void set_draw_handlers();
    void clear_draw_handlers();
    bool create_sw_canvas(int surface_id, int width, int height, uint32_t format);
#ifdef USE_OGL
    bool create_ogl_canvas(int surface_id, int width, int height, uint32_t format, bool recreate,
                           RenderType rendertype);
#endif
#ifdef WIN32
    bool create_gdi_canvas(int surface_id, int width, int height, uint32_t format);
#endif
    void destroy_canvas(int surface_id);
    void create_canvas(int surface_id, const std::vector<int>& canvas_type, int width, int height,
                       uint32_t format);
    void destroy_strams();
    void update_cursor();

    void create_primary_surface(int width, int height, uint32_t format);
    void create_surface(int surface_id, int width, int height, uint32_t format);
    void destroy_primary_surface();
    void destroy_surface(int surface_id);

    void handle_mode(RedPeer::InMessage* message);
    void handle_mark(RedPeer::InMessage* message);
    void handle_reset(RedPeer::InMessage* message);

    void handle_inval_list(RedPeer::InMessage* message);
    void handle_inval_all_pixmaps(RedPeer::InMessage* message);
    void handle_inval_palette(RedPeer::InMessage* message);
    void handle_inval_all_palettes(RedPeer::InMessage* message);
    void handle_copy_bits(RedPeer::InMessage* message);
    void handle_stream_create(RedPeer::InMessage* message);
    void handle_stream_data(RedPeer::InMessage* message);
    void handle_stream_clip(RedPeer::InMessage* message);
    void handle_stream_destroy(RedPeer::InMessage* message);
    void handle_stream_destroy_all(RedPeer::InMessage* message);

    void handle_surface_create(RedPeer::InMessage* message);
    void handle_surface_destroy(RedPeer::InMessage* message);

    void handle_draw_fill(RedPeer::InMessage* message);
    void handle_draw_opaque(RedPeer::InMessage* message);
    void handle_draw_copy(RedPeer::InMessage* message);
    void handle_draw_blend(RedPeer::InMessage* message);
    void handle_draw_blackness(RedPeer::InMessage* message);
    void handle_draw_whiteness(RedPeer::InMessage* message);
    void handle_draw_invers(RedPeer::InMessage* message);
    void handle_draw_rop3(RedPeer::InMessage* message);
    void handle_draw_stroke(RedPeer::InMessage* message);
    void handle_draw_text(RedPeer::InMessage* message);
    void handle_draw_transparent(RedPeer::InMessage* message);
    void handle_draw_alpha_blend(RedPeer::InMessage* message);

    void on_streams_trigger();
    virtual void on_update_completion(uint64_t mark);
    void streams_time();
    void activate_streams_timer();
    void stream_update_request(uint32_t update_time);

    static void set_clip_rects(const SpiceClip& clip, uint32_t& num_clip_rects, SpiceRect*& clip_rects);
private:
    DisplaySurfacesManger surfaces_mngr;
    PixmapCache& _pixmap_cache;
    PaletteCache _palette_cache;
    GlzDecoderWindow& _glz_window;
    bool _mark;
    int _x_res;
    int _y_res;
    uint32_t _format;
#ifdef USE_OGL
    RenderType _rendertype;
#endif

#ifndef RED64
    Mutex _mark_lock;
#endif
    uint64_t _update_mark;
    Mutex _streams_lock;

    Mutex _timer_lock;
    AutoRef<StreamsTimer> _streams_timer;
    uint32_t _next_timer_time;

    AutoRef<CursorData> _cursor;
    bool _cursor_visibal;
    bool _active_pointer;
    bool _capture_mouse_mode;
    InputsChannel* _inputs_channel;

    SpicePoint _pointer_pos;
    int _buttons_state;

    std::vector<VideoStream*> _streams;
    VideoStream* _active_streams;
    StreamsTrigger _streams_trigger;
#ifdef USE_OGL
    GLInterruptRecreate _gl_interrupt_recreate;
#endif
    InterruptUpdate _interrupt_update;

    friend class SetModeEvent;
    friend class CreatePrimarySurfaceEvent;
    friend class DestroyPrimarySurfaceEvent;
    friend class CreateSurfaceEvent;
    friend class DestroySurfaceEvent;
    friend class ActivateTimerEvent;
    friend class VideoStream;
    friend class StreamsTrigger;
    friend class GLInterupt;
    friend class StreamsTimer;
    friend class AttachChannelsEvent;
    friend class DetachChannelsEvent;
};

#endif