blob: 5980a86126d5e8c256051e818818e6768e0f9d8a [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef GUAC_DISPLAY_PRIV_H
#define GUAC_DISPLAY_PRIV_H
#include "display-plan.h"
#include "guacamole/client.h"
#include "guacamole/display.h"
#include "guacamole/fifo.h"
#include "guacamole/rect.h"
#include "guacamole/socket.h"
#include <pthread.h>
/**
* The maximum amount of time to wait after flushing a frame when compensating
* for client-side processing delays, in milliseconds. If a connected client is
* taking longer than this amount of additional time to process a received
* frame, processing lag compensation will be only partial (to avoid delaying
* further processing without bound for extremely slow clients).
*/
#define GUAC_DISPLAY_MAX_LAG_COMPENSATION 500
/*
* IMPORTANT: All functions defined within the internals of guac_display that
* DO NOT acquire locks on their own are given prefixes based on whether they
* access or modify the pending frame, last frame, or both. It is the
* responsibility of the caller of such functions to ensure that the required
* locks are either held or not relevant.
*
* The prefixes that may be added to function names are:
*
* "PFR_"
* The function reads (but does not write) the state of the pending frame.
* This prefix and "PFW_" are mutually-exclusive.
*
* "PFW_"
* The function writes (and possibly reads) the state of the pending frame.
* This prefix and "PFW_" are mutually-exclusive.
*
* "LFR_"
* The function reads (but does not write) the state of the last frame.
* This prefix and "LFW_" are mutually-exclusive.
*
* "LFW_"
* The function writes (and possibly reads) the state of the last frame.
* This prefix and "LFR_" are mutually-exclusive.
*
* "XFR_"
* The function reads (but does not write) the state of a frame, and
* whether that frame is the pending frame or the last frame depends on
* which frame is provided via function parameters. This prefix and "XFW_"
* are mutually-exclusive.
*
* "XFW_"
* The function writes (but does not read) the state of a frame, and
* whether that frame is the pending frame or the last frame depends on
* which frame is provided via function parameters. This prefix and "XFR_"
* are mutually-exclusive.
*
* Any functions lacking these prefixes either do not access last/pending
* frames in any way or take care of acquiring/releasing locks entirely on
* their own.
*
* These conventions are used for all functions in the internals of
* guac_display, not just those defined in this header.
*/
/*
* IMPORTANT: In cases where a single thread must acquire multiple locks used
* by guac_display, proper acquisition order must be observed to avoid
* deadlock. The correct order is:
*
* 1) pending_frame.lock
* 2) last_frame.lock
* 3) ops
* 4) render_state
*
* Acquiring these locks in any other order risks deadlock. Don't do it.
*/
/**
* The size of the image tiles (cells) that will be used to track changes to
* each layer, including gathering framerate statistics and performing indexing
* based on contents. Each side of each cell will consist of this many pixels.
*
* IMPORTANT: The hashing algorithm used to search the previous frame for
* content in the pending frame that has been reused (ie: scrolling) strongly
* depends on this value being 64. Any adjustment to this value will require
* corresponding and careful changes to the hashing algorithm.
*/
#define GUAC_DISPLAY_CELL_SIZE 64
/**
* The exponent of the power-of-two value that dictates the size of the image
* tiles (cells) that will be used to track changes to each layer
* (GUAC_DISPLAY_CELL_SIZE).
*/
#define GUAC_DISPLAY_CELL_SIZE_EXPONENT 6
/**
* The amount that the width/height of internal storage for graphical data
* should be rounded up to avoid unnecessary reallocations and copying.
*/
#define GUAC_DISPLAY_RESIZE_FACTOR 64
/**
* Given the width (or height) of a layer in pixels, calculates the width (or
* height) of that layer's pending_frame_cells array in cells.
*
* NOTE: It is not necessary to recalculate these values except when resizing a
* layer. In all other cases, the width/height of a layer in cells can be found
* in the pending_frame_cells_width and pending_frame_cells_height members
* respectively.
*
* @param pixels
* The width or height of the layer, in pixels.
*
* @return
* The width or height of that layer's pending_frame_cells array, in cells.
*/
#define GUAC_DISPLAY_CELL_DIMENSION(pixels) \
((pixels + GUAC_DISPLAY_CELL_SIZE - 1) / GUAC_DISPLAY_CELL_SIZE)
/**
* The size of the operation FIFO read by the display worker threads. This
* value is the number of operation slots in the FIFO, not bytes. The amount of
* space currently specified here is roughly sufficient 8 worst-case frames
* worth of outstanding operations.
*/
#define GUAC_DISPLAY_WORKER_FIFO_SIZE ( \
GUAC_DISPLAY_MAX_WIDTH * GUAC_DISPLAY_MAX_HEIGHT \
/ GUAC_DISPLAY_CELL_SIZE \
/ GUAC_DISPLAY_CELL_SIZE \
* 8)
/**
* Returns the memory address of the given rectangle within the mutable image
* buffer of the given guac_display_layer_state, where the upper-left corner of
* the given buffer is (0, 0). If the memory address cannot be calculated
* because doing so would overflow the maximum value of a size_t, execution of
* the current process is automatically aborted.
*
* IMPORTANT: No checks are performed on whether the rectangle extends beyond
* the bounds of the buffer, including considering whether the left/top
* position of the rectangle is negative. If the rectangle has not already been
* contrained to be within the bounds of the buffer, such checks must be
* performed before dereferencing the value returned by this macro.
*
* @param layer_state
* The guac_display_layer_state associated with the image buffer within
* which the address of the given rectangle should be determined.
*
* @param rect
* The rectangle to determine the offset of.
*
* @return
* The memory address of the given rectangle within the buffer of the given
* layer state.
*/
#define GUAC_DISPLAY_LAYER_STATE_MUTABLE_BUFFER(layer_state, rect) \
GUAC_RECT_MUTABLE_BUFFER(rect, (layer_state).buffer, (layer_state).buffer_stride, GUAC_DISPLAY_LAYER_RAW_BPP)
/**
* Returns the memory address of the given rectangle within the immutable
* (const) image buffer of the given guac_display_layer_state, where the
* upper-left corner of the given buffer is (0, 0). If the memory address
* cannot be calculated because doing so would overflow the maximum value of a
* size_t, execution of the current process is automatically aborted.
*
* IMPORTANT: No checks are performed on whether the rectangle extends beyond
* the bounds of the buffer, including considering whether the left/top
* position of the rectangle is negative. If the rectangle has not already been
* contrained to be within the bounds of the buffer, such checks must be
* performed before dereferencing the value returned by this macro.
*
* @param layer_state
* The guac_display_layer_state associated with the image buffer within
* which the address of the given rectangle should be determined.
*
* @param rect
* The rectangle to determine the offset of.
*
* @return
* The memory address of the given rectangle within the buffer of the given
* layer state.
*/
#define GUAC_DISPLAY_LAYER_STATE_CONST_BUFFER(layer_state, rect) \
GUAC_RECT_CONST_BUFFER(rect, (layer_state).buffer, (layer_state).buffer_stride, GUAC_DISPLAY_LAYER_RAW_BPP)
/**
* Bitwise flag set on the render_state flag in guac_display when rendering of
* a pending frame is in progress (Guacamole instructions that draw the pending
* frame are being sent to connected users).
*/
#define GUAC_DISPLAY_RENDER_STATE_FRAME_IN_PROGRESS 1
/**
* Bitwise flag set on the render_state flag in guac_display when rendering of
* a pending frame is NOT in progress (Guacamole instructions that draw the
* pending frame are NOT being sent to connected users).
*/
#define GUAC_DISPLAY_RENDER_STATE_FRAME_NOT_IN_PROGRESS 2
/**
* Bitwise flag set on the render_state flag in guac_display when the
* guac_display has been stopped and all worker threads have terminated (no
* further frames will render). This flag is set when guac_display_stop() has
* been invoked, including as part of guac_display_free().
*/
#define GUAC_DISPLAY_RENDER_STATE_STOPPED 4
/**
* Bitwise flag that is set on the state of a guac_display_render_thread when
* the thread should be stopped.
*/
#define GUAC_DISPLAY_RENDER_THREAD_STATE_STOPPING 1
/**
* Bitwise flag that is set on the state of a guac_display_render_thread when
* visible, graphical changes have been made.
*/
#define GUAC_DISPLAY_RENDER_THREAD_STATE_FRAME_MODIFIED 2
/**
* Bitwise flag that is set on the state of a guac_display_render_thread when
* a frame boundary has been reached.
*/
#define GUAC_DISPLAY_RENDER_THREAD_STATE_FRAME_READY 4
/**
* The state of the mouse cursor, as independently tracked by the render
* thread. The mouse cursor state may be reported by
* guac_display_render_thread_notify_user_moved_mouse() to avoid unnecessarily
* locking the display within instruction handlers (which can otherwise result
* in delays in handling critical instructions like "sync").
*/
typedef struct guac_display_render_thread_cursor_state {
/**
* The user that moved or clicked the mouse.
*
* NOTE: This user is NOT guaranteed to still exist in memory. This may be
* a dangling pointer and must be validated before deferencing.
*/
guac_user* user;
/**
* The X coordinate of the mouse cursor.
*/
int x;
/**
* The Y coordinate of the mouse cursor.
*/
int y;
/**
* The mask representing the states of all mouse buttons.
*/
int mask;
} guac_display_render_thread_cursor_state;
struct guac_display_render_thread {
/**
* The display this render thread should render to.
*/
guac_display* display;
/**
* The actual underlying POSIX thread.
*/
pthread_t thread;
/**
* Flag representing render state. This flag is used to store whether the
* render thread is stopping and whether the current frame has been
* modified or is ready.
*
* @see GUAC_DISPLAY_RENDER_THREAD_STATE_STOPPING
* @see GUAC_DISPLAY_RENDER_THREAD_FRAME_MODIFIED
* @see GUAC_DISPLAY_RENDER_THREAD_FRAME_READY
*/
guac_flag state;
/**
* The current mouse cursor state, as reported by
* guac_display_render_thread_notify_user_moved_mouse().
*/
guac_display_render_thread_cursor_state cursor_state;
/**
* The number of frames that have been explicitly marked as ready since the
* last frame sent. This will be zero if explicit frame boundaries are not
* currently being used.
*/
unsigned int frames;
};
/**
* Approximation of how often a region of a layer is modified, as well as what
* changes have been made to that region since the last frame. This information
* is used to help advise future optimizations, such as whether lossy
* compression is appropriate and whether parts of the layer can be copied from
* other regions rather than resend image data.
*/
typedef struct guac_display_layer_cell {
/**
* The last time this particular cell was part of a frame (used to
* calculate framerate).
*/
guac_timestamp last_frame;
/**
* The region of this cell that has been modified since the last frame was
* flushed. If the cell has not been modified at all, this will be an empty
* rect.
*/
guac_rect dirty;
/**
* The rough number of pixels in the dirty rect that have been modified. If
* the cell has not been modified at all, this will be zero.
*/
size_t dirty_size;
/**
* The display plan operation that is associated with this cell. If a
* display plan is not currently being created or optimized, this will be
* NULL.
*/
guac_display_plan_operation* related_op;
} guac_display_layer_cell;
/**
* The state of a Guacamole layer or buffer at some point in time. Within
* guac_display_layer, copies of this structure are used to represent the
* previous frame and the current, in-progress frame. The previous and
* in-progress frames are compared during flush to determine what graphical
* operations need to be sent to connected clients to efficiently transform the
* remote display from its previous state to the now-current state.
*
* IMPORTANT: The lock of the corresponding guac_display_state must be acquired
* before reading or modifying the values of any member of this structure.
*/
typedef struct guac_display_layer_state {
/**
* The width of this layer in pixels.
*/
int width;
/**
* The height of this layer in pixels.
*/
int height;
/**
* The layer which contains this layer. This is only applicable to visible
* (non-buffer) layers which are not the default layer.
*/
const guac_layer* parent;
/**
* The X coordinate of the upper-left corner of this layer, in pixels,
* relative to its parent layer. This is only applicable to visible
* (non-buffer) layers which are not the default layer.
*/
int x;
/**
* The Y coordinate of the upper-left corner of this layer, in pixels,
* relative to its parent layer. This is only applicable to visible
* (non-buffer) layers which are not the default layer.
*/
int y;
/**
* The Z-order of this layer, relative to sibling layers. This is only
* applicable to visible (non-buffer) layers which are not the default
* layer.
*/
int z;
/**
* The level of opacity applied to this layer. Fully opaque is 255, while
* fully transparent is 0. This is only applicable to visible (non-buffer)
* layers which are not the default layer.
*/
int opacity;
/**
* The number of simultaneous touches that this surface can accept, where 0
* indicates that the surface does not support touch events at all.
*/
int touches;
/**
* Non-zero if all graphical updates for this surface should use lossless
* compression, 0 otherwise. By default, newly-created surfaces will use
* lossy compression when heuristics determine it is appropriate.
*/
int lossless;
/**
* The raw, 32-bit buffer of ARGB image data. If the layer was allocated as
* opaque, the alpha channel of each ARGB pixel will not be considered when
* compositing or when encoding images.
*
* So that large regions of image data can be easily compared, a consistent
* value for the alpha channel SHOULD be provided so that each 32-bit pixel
* can be compared without having to separately masking the channel.
* Optimizations within guac_display, including scroll detection, may
* assume that the alpha channel can always be considered when comparing
* pixel values for equivalence.
*/
unsigned char* buffer;
/**
* The width of the image data, in pixels. This is not necessarily the same
* as the width of the layer.
*/
int buffer_width;
/**
* The height of the image data, in pixels. This is not necessarily the
* same as the height of the layer.
*/
int buffer_height;
/**
* The number of bytes in each row of image data. This is not necessarily
* equivalent to 4 * width.
*/
size_t buffer_stride;
/**
* Non-zero if the image data referenced by the buffer pointer was
* allocated externally and should not be automatically freed or managed by
* guac_display, zero otherwise.
*/
int buffer_is_external;
/**
* The approximate rectangular region containing all pixels within this
* layer that have been modified since the frame that occurred before this
* frame. If the layer was not modified, this will be an empty rect (zero
* width or zero height).
*/
guac_rect dirty;
/**
* Whether this layer should be searched for possible scroll/copy
* optimizations.
*/
int search_for_copies;
/* ---------------- LAYER LIST POINTERS ---------------- */
/**
* The layer immediately prior to this layer within the list containing
* this layer, or NULL if this is the first layer/buffer in the list.
*/
guac_display_layer* prev;
/**
* The layer immediately following this layer within the list containing
* this layer, or NULL if this is the last layer/buffer in the list.
*/
guac_display_layer* next;
} guac_display_layer_state;
struct guac_display_layer {
/**
* The guac_display instance that allocated this layer/buffer.
*/
guac_display* display;
/**
* The Guacamole layer (or buffer) that this guac_display_layer will draw
* to when flushing a frame.
*
* NOTE: This value is set only during allocation and may safely be
* accessed without acquiring the overall layer lock.
*/
const guac_layer* layer;
/**
* Whether the graphical data that will be written to this layer/buffer
* will only ever be opaque (no alpha channel). Compositing of graphical
* updates can be faster when no alpha channel need be considered.
*/
int opaque;
/**
* Lock used to ensure sequences of Guacamole protocol path instructions
* for this layer are not interleaved when sent from concurrent threads.
*/
pthread_mutex_t path_lock;
/* ---------------- LAYER PREVIOUS FRAME STATE ---------------- */
/**
* The state of this layer when the last frame was flushed to connected clients.
*
* IMPORTANT: The display-level last_frame.lock MUST be acquired before
* modifying or reading this member.
*/
guac_display_layer_state last_frame;
/**
* Off-screen buffer storing the contents of the previously-rendered frame
* for later use. If graphical updates are recognized as reusing data from
* a previous frame, that data will be copied from this buffer. Doing this
* simplifies the copy operation (there is no longer any need to perform
* those copies in a specific order) and ensures the copies are efficient
* on the client side (copying from one part of a graphical surface to
* another part of the same surface can be inefficient, particularly if the
* regions overlap). In practice, there is ample time between frames for
* the client to copy a layer's current contents to an off-screen buffer
* while awaiting the next frame.
*
* NOTE: This value is set only during allocation and may safely be
* accessed without acquiring the display-level last_frame.lock.
*/
guac_layer* last_frame_buffer;
/* ---------------- LAYER PENDING FRAME STATE ---------------- */
/**
* The upcoming state of this layer when the current, in-progress frame is
* flushed to connected clients.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
guac_display_layer_state pending_frame;
/**
* The Cairo context and surface containing the graphical data of the
* pending frame. The actual underlying buffer and details of the graphical
* surface are also available via pending_frame_raw_context.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
guac_display_layer_cairo_context pending_frame_cairo_context;
/**
* The raw underlying buffer and details of the surface containing the
* graphical data of the pending frame. A Cairo context and surface backed
* by this buffer are also available via pending_frame_cairo_context.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
guac_display_layer_raw_context pending_frame_raw_context;
/**
* A two-dimensional array of square tiles representing the nature of
* changes made to corresponding regions of the display. This is used both
* to track how frequently certain regions are being updated (to help
* inform whether lossy compression is appropriate), to track what parts of
* the frame have actually changed, and to aid in determining whether
* adjacent updated regions should be combined into a single update.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
guac_display_layer_cell* pending_frame_cells;
/**
* The width of the pending_frame_cells array, in cells.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
size_t pending_frame_cells_width;
/**
* The height of the pending_frame_cells array, in cells.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
size_t pending_frame_cells_height;
/**
* The next layer within the list of layers that have been removed from
* the pending frame and are awaiting destruction, or NULL if this is the
* last such layer. This value is meaningful only for layers that have been
* removed from the pending frame layer list.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
guac_display_layer* next_removed;
};
typedef struct guac_display_state {
/**
* Lock that guards concurrent access to any member of ANY STRUCTURE that
* relates to this guac_display_state, including the members of this
* structure. Unless explicitly documented otherwise, this lock MUST be
* acquired before accessing or modifying the members of this
* guac_display_state or any nested structure.
*/
guac_rwlock lock;
/**
* The specific point in time that this guac_display_state represents.
*/
guac_timestamp timestamp;
/**
* All layers and buffers that were part of the display at the time that
* the frame/snapshot represented by this guac_display_state was updated.
*
* NOTE: For each guac_display, there are two distinct lists of layers: the
* last frame layer list and the pending frame layer list:
*
* LAST FRAME LAYER LIST
*
* - HEAD: display->last_frame.layers
* - NEXT: layer->last_frame.next
* - PREV: layer->last_frame.prev
*
* PENDING LAYER LIST
*
* - HEAD: display->pending_frame.layers
* - NEXT: layer->pending_frame.next
* - PREV: layer->pending_frame.prev
*
* Layers are added to and removed from only the pending frame layer list.
* The last frame layer list is rebuilt from the pending frame layer list
* each time a frame is flushed, so an added or removed layer takes effect
* on the last frame only at that point. A removed layer is freed only
* after a flush has dropped it from the last frame layer list (see the
* pending_frame_removed_layers member of guac_display and
* guac_display_free_removed_layers()).
*/
guac_display_layer* layers;
/**
* The X coordinate of the hotspot of the mouse cursor. The cursor image is
* stored/updated via the cursor_buffer member of guac_display.
*/
int cursor_hotspot_x;
/**
* The Y coordinate of the hotspot of the mouse cursor. The cursor image is
* stored/updated via the cursor_buffer member of guac_display.
*/
int cursor_hotspot_y;
/**
* The user that moved or clicked the mouse. This is used to ensure we
* don't attempt to synchronize an out-of-date mouse position to the user
* that is actively moving the mouse.
*
* NOTE: This user is NOT guaranteed to still exist in memory. This may be
* a dangling pointer and must be validated before deferencing.
*/
guac_user* cursor_user;
/**
* The X coordinate of the mouse cursor.
*/
int cursor_x;
/**
* The Y coordinate of the mouse cursor.
*/
int cursor_y;
/**
* The mask representing the states of all mouse buttons.
*/
int cursor_mask;
/**
* The number of logical frames that have been rendered to this display
* state since the previous display state.
*/
unsigned int frames;
} guac_display_state;
struct guac_display {
/* NOTE: Any member of this structure that requires protection against
* concurrent access is protected by its own lock. The overall display does
* not have nor need a top-level lock. */
/**
* The client associated with this display.
*/
guac_client* client;
/* ---------------- DISPLAY FRAME STATES ---------------- */
/**
* The state of this display at the time the last frame was sent to
* connected users.
*/
guac_display_state last_frame;
/**
* The pending state of this display that will become the next frame once
* it is sent to connected users.
*/
guac_display_state pending_frame;
/**
* Whether the pending frame has been modified in any way outside of
* changing the mouse cursor or moving the mouse. This is used to help
* inform whether a frame should be flushed to update connected clients
* with respect to mouse cursor changes, or whether those changes can be
* safely assumed to be part of a larger frame containing general graphical
* updates.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
int pending_frame_dirty_excluding_mouse;
/**
* The head of the list of layers that have been removed from the pending
* frame but cannot be freed until the frame is flushed. This list is
* iterated via the next_removed member of guac_display_layer.
*
* IMPORTANT: The display-level pending_frame.lock MUST be acquired before
* modifying or reading this member.
*/
guac_display_layer* pending_frame_removed_layers;
/* ---------------- WELL-KNOWN LAYERS / BUFFERS ---------------- */
/**
* The default layer of the client display.
*/
guac_display_layer* default_layer;
/**
* The buffer storing the current mouse cursor. The hotspot position within
* the cursor is stored within cursor_hotspot_x and cursor_hotspot_y of
* guac_display_state.
*/
guac_display_layer* cursor_buffer;
/* ---------------- FRAME ENCODING WORKER THREADS ---------------- */
/**
* The number of worker threads in the worker_threads array.
*/
int worker_thread_count;
/**
* Pool of worker threads that automatically pull from the ops FIFO,
* sending corresponding Guacamole instructions to all connected clients.
*/
pthread_t* worker_threads;
/**
* FIFO of all graphical operations required to transform the remote
* display state from the previous frame to the next frame. Operations
* added to this FIFO will automatically be pulled and processed by a
* worker thread.
*/
guac_fifo ops;
/**
* Storage for any items within the ops fifo.
*/
guac_display_plan_operation ops_items[GUAC_DISPLAY_WORKER_FIFO_SIZE];
/**
* The current number of active worker threads.
*
* IMPORTANT: This member must only be accessed or modified while the ops
* FIFO is locked.
*/
unsigned int active_workers;
/**
* Whether least one pending frame has been deferred due to the encoding
* process being underway for a previous frame at the time it was
* completed.
*
* IMPORTANT: This member must only be accessed or modified while the ops
* FIFO is locked.
*/
int frame_deferred;
/**
* The current state of the rendering process. Code that needs to be aware
* of whether a frame is currently in the process of being rendered can
* monitor the state of this flag, watching for either the
* GUAC_DISPLAY_RENDER_STATE_FRAME_IN_PROGRESS or
* GUAC_DISPLAY_RENDER_STATE_FRAME_NOT_IN_PROGRESS values.
*/
guac_flag render_state;
};
/**
* Allocates and inserts a new element into the given linked list of display
* layers, associating it with the given layer and surface.
*
* @param head
* A pointer to the head pointer of the list of layers. The head pointer
* will be updated by this function to point to the newly-allocated
* display layer.
*
* @param layer
* The Guacamole layer to associated with the new display layer.
*
* @param opaque
* Non-zero if the new layer will only ever contain opaque image contents
* (the alpha channel should be ignored), zero otherwise.
*
* @return
* The newly-allocated display layer, which has been associated with the
* provided layer and surface.
*/
guac_display_layer* guac_display_add_layer(guac_display* display, guac_layer* layer, int opaque);
/**
* Removes the given layer from the pending frame layer list. The layer is not
* immediately freed, but is instead scheduled to be freed via the
* pending_frame_removed_layers list of the display. It will finally be freed
* and removed from the last frame list when the frame is flushed.
*
* @param display_layer
* The layer to remove.
*/
void guac_display_remove_layer(guac_display_layer* display_layer);
/**
* Frees the list of layers that are awaiting removal from a previous call to
* guac_display_remove_layer(). This function is safe to call only after all
* removed layers are not part of any outstanding frame, including any
* operations that may not yet have been flushed by the worker threads.
*
* @param display
* The display that the layers were removed from.
*
* @param removed_layers
* The head of the list of removed layers to free, linked via the
* next_removed member of guac_display_layer, or NULL if there are no such
* layers.
*/
void guac_display_free_removed_layers(guac_display* display,
guac_display_layer* removed_layers);
/**
* Resizes the given layer to the given dimensions, including any underlying
* image buffers.
*
* @param layer
* The layer to resize.
*
* @param width
* The new width, in pixels.
*
* @param height
* The new height, in pixels.
*/
void PFW_guac_display_layer_resize(guac_display_layer* layer,
int width, int height);
/**
* Worker thread that continuously pulls operations from the operation FIFO of
* the given guac_display, applying those operations by seding corresponding
* instructions to connected clients.
*
* @param data
* A pointer to the guac_display.
*
* @return
* Always NULL.
*/
void* guac_display_worker_thread(void* data);
#endif