aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesalib/Makefile12
-rw-r--r--mesalib/configs/darwin24
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_debug.h862
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_fbo.c3
-rw-r--r--xorg-server/randr/rrcrtc.c3012
5 files changed, 1965 insertions, 1948 deletions
diff --git a/mesalib/Makefile b/mesalib/Makefile
index 7a5dae762..f3c0a20a3 100644
--- a/mesalib/Makefile
+++ b/mesalib/Makefile
@@ -364,12 +364,24 @@ GALLIUM_FILES = \
$(DIRECTORY)/src/gallium/*/*/*/*.[ch] \
$(DIRECTORY)/src/gallium/*/*/*/*.py
+APPLE_DRI_FILES = \
+ $(DIRECTORY)/src/glx/apple/Makefile \
+ $(DIRECTORY)/src/glx/apple/*.[ch] \
+ $(DIRECTORY)/src/glx/apple/*.tcl \
+ $(DIRECTORY)/src/glx/apple/apple_exports.list \
+ $(DIRECTORY)/src/glx/apple/GL_aliases \
+ $(DIRECTORY)/src/glx/apple/GL_extensions \
+ $(DIRECTORY)/src/glx/apple/GL_noop \
+ $(DIRECTORY)/src/glx/apple/GL_promoted \
+ $(DIRECTORY)/src/glx/apple/specs/*.spec \
+ $(DIRECTORY)/src/glx/apple/specs/*.tm
DRI_FILES = \
$(DIRECTORY)/include/GL/internal/dri_interface.h \
$(DIRECTORY)/include/GL/internal/sarea.h \
$(DIRECTORY)/src/glx/Makefile \
$(DIRECTORY)/src/glx/*.[ch] \
+ $(APPLE_DRI_FILES) \
$(DIRECTORY)/src/mesa/drivers/dri/Makefile \
$(DIRECTORY)/src/mesa/drivers/dri/Makefile.template \
$(DIRECTORY)/src/mesa/drivers/dri/dri.pc.in \
diff --git a/mesalib/configs/darwin b/mesalib/configs/darwin
index 990610724..3cf1110b4 100644
--- a/mesalib/configs/darwin
+++ b/mesalib/configs/darwin
@@ -31,18 +31,20 @@ CXXFLAGS = -ggdb3 -Os -Wall -fno-strict-aliasing \
-I$(INSTALL_DIR)/include -I$(X11_DIR)/include $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(ASM_FLAGS) $(DEFINES)
# Library names (actual file names)
-GL_LIB_NAME = libGL.dylib
-GLU_LIB_NAME = libGLU.dylib
-GLUT_LIB_NAME = libglut.dylib
-GLW_LIB_NAME = libGLw.dylib
-OSMESA_LIB_NAME = libOSMesa.dylib
+GL_LIB_NAME = lib$(GL_LIB).dylib
+GLU_LIB_NAME = lib$(GLU_LIB).dylib
+GLUT_LIB_NAME = lib$(GLUT_LIB).dylib
+GLW_LIB_NAME = lib$(GLW_LIB).dylib
+OSMESA_LIB_NAME = lib$(OSMESA_LIB).dylib
+VG_LIB_NAME = lib$(VG_LIB).dylib
# globs used to install the lib and all symlinks
-GL_LIB_GLOB = libGL.*dylib
-GLU_LIB_GLOB = libGLU.*dylib
-GLUT_LIB_GLOB = libglut.*dylib
-GLW_LIB_GLOB = libGLw.*dylib
-OSMESA_LIB_GLOB = libOSMesa.*dylib
+GL_LIB_GLOB = lib$(GL_LIB).*dylib
+GLU_LIB_GLOB = lib$(GLU_LIB).*dylib
+GLUT_LIB_GLOB = lib$(GLUT_LIB).*dylib
+GLW_LIB_GLOB = lib$(GLW_LIB).*dylib
+OSMESA_LIB_GLOB = lib$(OSMESA_LIB).*dylib
+VG_LIB_GLOB = lib$(VG_LIB).*.dylib
GL_LIB_DEPS = -L$(INSTALL_DIR)/$(LIB_DIR) -L$(X11_DIR)/$(LIB_DIR) -lX11 -lXext -lm -lpthread
OSMESA_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB)
@@ -57,3 +59,5 @@ GLU_DIRS = sgi
DRIVER_DIRS = osmesa
#DRIVER_DIRS = dri
DRI_DIRS = swrast
+GALLIUM_DRIVERS_DIRS = softpipe trace rbug noop identity galahad failover
+#GALLIUM_DRIVERS_DIRS += llvmpipe
diff --git a/mesalib/src/gallium/auxiliary/util/u_debug.h b/mesalib/src/gallium/auxiliary/util/u_debug.h
index e3efac41b..b5ea40506 100644
--- a/mesalib/src/gallium/auxiliary/util/u_debug.h
+++ b/mesalib/src/gallium/auxiliary/util/u_debug.h
@@ -1,431 +1,431 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * @file
- * Cross-platform debugging helpers.
- *
- * For now it just has assert and printf replacements, but it might be extended
- * with stack trace reports and more advanced logging in the near future.
- *
- * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
- */
-
-#ifndef U_DEBUG_H_
-#define U_DEBUG_H_
-
-
-#include "os/os_misc.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#if defined(__GNUC__)
-#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
-#else
-#define _util_printf_format(fmt, list)
-#endif
-
-void _debug_vprintf(const char *format, va_list ap);
-
-
-static INLINE void
-_debug_printf(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- _debug_vprintf(format, ap);
- va_end(ap);
-}
-
-
-/**
- * Print debug messages.
- *
- * The actual channel used to output debug message is platform specific. To
- * avoid misformating or truncation, follow these rules of thumb:
- * - output whole lines
- * - avoid outputing large strings (512 bytes is the current maximum length
- * that is guaranteed to be printed in all platforms)
- */
-#if !defined(PIPE_OS_HAIKU)
-static INLINE void
-debug_printf(const char *format, ...) _util_printf_format(1,2);
-
-static INLINE void
-debug_printf(const char *format, ...)
-{
-#ifdef DEBUG
- va_list ap;
- va_start(ap, format);
- _debug_vprintf(format, ap);
- va_end(ap);
-#else
- (void) format; /* silence warning */
-#endif
-}
-
-#endif /* !PIPE_OS_HAIKU */
-
-/*
- * ... isn't portable so we need to pass arguments in parentheses.
- *
- * usage:
- * debug_printf_once(("awnser: %i\n", 42));
- */
-#define debug_printf_once(args) \
- do { \
- static boolean once = TRUE; \
- if (once) { \
- once = FALSE; \
- debug_printf args; \
- } \
- } while (0)
-
-
-#ifdef DEBUG
-#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
-#else
-#define debug_vprintf(_format, _ap) ((void)0)
-#endif
-
-
-#ifdef DEBUG
-/**
- * Dump a blob in hex to the same place that debug_printf sends its
- * messages.
- */
-void debug_print_blob( const char *name, const void *blob, unsigned size );
-
-/* Print a message along with a prettified format string
- */
-void debug_print_format(const char *msg, unsigned fmt );
-#else
-#define debug_print_blob(_name, _blob, _size) ((void)0)
-#define debug_print_format(_msg, _fmt) ((void)0)
-#endif
-
-
-/**
- * Hard-coded breakpoint.
- */
-#ifdef DEBUG
-#define debug_break() os_break()
-#else /* !DEBUG */
-#define debug_break() ((void)0)
-#endif /* !DEBUG */
-
-
-long
-debug_get_num_option(const char *name, long dfault);
-
-void _debug_assert_fail(const char *expr,
- const char *file,
- unsigned line,
- const char *function);
-
-
-/**
- * Assert macro
- *
- * Do not expect that the assert call terminates -- errors must be handled
- * regardless of assert behavior.
- *
- * For non debug builds the assert macro will expand to a no-op, so do not
- * call functions with side effects in the assert expression.
- */
-#ifdef DEBUG
-#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
-#else
-#define debug_assert(expr) do { } while (0 && (expr))
-#endif
-
-
-/** Override standard assert macro */
-#ifdef assert
-#undef assert
-#endif
-#define assert(expr) debug_assert(expr)
-
-
-/**
- * Output the current function name.
- */
-#ifdef DEBUG
-#define debug_checkpoint() \
- _debug_printf("%s\n", __FUNCTION__)
-#else
-#define debug_checkpoint() \
- ((void)0)
-#endif
-
-
-/**
- * Output the full source code position.
- */
-#ifdef DEBUG
-#define debug_checkpoint_full() \
- _debug_printf("%s:%u:%s", __FILE__, __LINE__, __FUNCTION__)
-#else
-#define debug_checkpoint_full() \
- ((void)0)
-#endif
-
-
-/**
- * Output a warning message. Muted on release version.
- */
-#ifdef DEBUG
-#define debug_warning(__msg) \
- _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
-#else
-#define debug_warning(__msg) \
- ((void)0)
-#endif
-
-
-/**
- * Output an error message. Not muted on release version.
- */
-#ifdef DEBUG
-#define debug_error(__msg) \
- _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
-#else
-#define debug_error(__msg) \
- _debug_printf("error: %s\n", __msg)
-#endif
-
-
-/**
- * Used by debug_dump_enum and debug_dump_flags to describe symbols.
- */
-struct debug_named_value
-{
- const char *name;
- unsigned long value;
- const char *desc;
-};
-
-
-/**
- * Some C pre-processor magic to simplify creating named values.
- *
- * Example:
- * @code
- * static const debug_named_value my_names[] = {
- * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
- * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
- * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
- * DEBUG_NAMED_VALUE_END
- * };
- *
- * ...
- * debug_printf("%s = %s\n",
- * name,
- * debug_dump_enum(my_names, my_value));
- * ...
- * @endcode
- */
-#define DEBUG_NAMED_VALUE(__symbol) DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, NULL)
-#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
-#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
-
-
-/**
- * Convert a enum value to a string.
- */
-const char *
-debug_dump_enum(const struct debug_named_value *names,
- unsigned long value);
-
-const char *
-debug_dump_enum_noprefix(const struct debug_named_value *names,
- const char *prefix,
- unsigned long value);
-
-
-/**
- * Convert binary flags value to a string.
- */
-const char *
-debug_dump_flags(const struct debug_named_value *names,
- unsigned long value);
-
-
-/**
- * Function enter exit loggers
- */
-#ifdef DEBUG
-int debug_funclog_enter(const char* f, const int line, const char* file);
-void debug_funclog_exit(const char* f, const int line, const char* file);
-void debug_funclog_enter_exit(const char* f, const int line, const char* file);
-
-#define DEBUG_FUNCLOG_ENTER() \
- int __debug_decleration_work_around = \
- debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
-#define DEBUG_FUNCLOG_EXIT() \
- do { \
- (void)__debug_decleration_work_around; \
- debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
- return; \
- } while(0)
-#define DEBUG_FUNCLOG_EXIT_RET(ret) \
- do { \
- (void)__debug_decleration_work_around; \
- debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
- return ret; \
- } while(0)
-#define DEBUG_FUNCLOG_ENTER_EXIT() \
- debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
-
-#else
-#define DEBUG_FUNCLOG_ENTER() \
- int __debug_decleration_work_around
-#define DEBUG_FUNCLOG_EXIT() \
- do { (void)__debug_decleration_work_around; return; } while(0)
-#define DEBUG_FUNCLOG_EXIT_RET(ret) \
- do { (void)__debug_decleration_work_around; return ret; } while(0)
-#define DEBUG_FUNCLOG_ENTER_EXIT()
-#endif
-
-
-/**
- * Get option.
- *
- * It is an alias for getenv on Linux.
- *
- * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
- * endings with one option per line as
- *
- * NAME=value
- *
- * This file must be terminated with an extra empty line.
- */
-const char *
-debug_get_option(const char *name, const char *dfault);
-
-boolean
-debug_get_bool_option(const char *name, boolean dfault);
-
-long
-debug_get_num_option(const char *name, long dfault);
-
-unsigned long
-debug_get_flags_option(const char *name,
- const struct debug_named_value *flags,
- unsigned long dfault);
-
-#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
-static boolean \
-debug_get_option_ ## sufix (void) \
-{ \
- static boolean first = TRUE; \
- static boolean value; \
- if (first) { \
- first = FALSE; \
- value = debug_get_bool_option(name, dfault); \
- } \
- return value; \
-}
-
-#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
-static long \
-debug_get_option_ ## sufix (void) \
-{ \
- static boolean first = TRUE; \
- static long value; \
- if (first) { \
- first = FALSE; \
- value = debug_get_num_option(name, dfault); \
- } \
- return value; \
-}
-
-#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
-static unsigned long \
-debug_get_option_ ## sufix (void) \
-{ \
- static boolean first = TRUE; \
- static unsigned long value; \
- if (first) { \
- first = FALSE; \
- value = debug_get_flags_option(name, flags, dfault); \
- } \
- return value; \
-}
-
-
-unsigned long
-debug_memory_begin(void);
-
-void
-debug_memory_end(unsigned long beginning);
-
-
-#ifdef DEBUG
-struct pipe_context;
-struct pipe_surface;
-struct pipe_transfer;
-struct pipe_resource;
-
-void debug_dump_image(const char *prefix,
- unsigned format, unsigned cpp,
- unsigned width, unsigned height,
- unsigned stride,
- const void *data);
-void debug_dump_surface(struct pipe_context *pipe,
- const char *prefix,
- struct pipe_surface *surface);
-void debug_dump_texture(struct pipe_context *pipe,
- const char *prefix,
- struct pipe_resource *texture);
-void debug_dump_surface_bmp(struct pipe_context *pipe,
- const char *filename,
- struct pipe_surface *surface);
-void debug_dump_transfer_bmp(struct pipe_context *pipe,
- const char *filename,
- struct pipe_transfer *transfer);
-void debug_dump_float_rgba_bmp(const char *filename,
- unsigned width, unsigned height,
- float *rgba, unsigned stride);
-#else
-#define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0)
-#define debug_dump_surface(pipe, prefix, surface) ((void)0)
-#define debug_dump_surface_bmp(pipe, filename, surface) ((void)0)
-#define debug_dump_transfer_bmp(filename, transfer) ((void)0)
-#define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0)
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* U_DEBUG_H_ */
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Cross-platform debugging helpers.
+ *
+ * For now it just has assert and printf replacements, but it might be extended
+ * with stack trace reports and more advanced logging in the near future.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef U_DEBUG_H_
+#define U_DEBUG_H_
+
+
+#include "os/os_misc.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(__GNUC__)
+#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
+#else
+#define _util_printf_format(fmt, list)
+#endif
+
+void _debug_vprintf(const char *format, va_list ap);
+
+
+static INLINE void
+_debug_printf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ _debug_vprintf(format, ap);
+ va_end(ap);
+}
+
+
+/**
+ * Print debug messages.
+ *
+ * The actual channel used to output debug message is platform specific. To
+ * avoid misformating or truncation, follow these rules of thumb:
+ * - output whole lines
+ * - avoid outputing large strings (512 bytes is the current maximum length
+ * that is guaranteed to be printed in all platforms)
+ */
+#if !defined(PIPE_OS_HAIKU)
+static INLINE void
+debug_printf(const char *format, ...) _util_printf_format(1,2);
+
+static INLINE void
+debug_printf(const char *format, ...)
+{
+#ifdef DEBUG
+ va_list ap;
+ va_start(ap, format);
+ _debug_vprintf(format, ap);
+ va_end(ap);
+#else
+ (void) format; /* silence warning */
+#endif
+}
+
+#endif /* !PIPE_OS_HAIKU */
+
+/*
+ * ... isn't portable so we need to pass arguments in parentheses.
+ *
+ * usage:
+ * debug_printf_once(("awnser: %i\n", 42));
+ */
+#define debug_printf_once(args) \
+ do { \
+ static boolean once = TRUE; \
+ if (once) { \
+ once = FALSE; \
+ debug_printf args; \
+ } \
+ } while (0)
+
+
+#ifdef DEBUG
+#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
+#else
+#define debug_vprintf(_format, _ap) ((void)0)
+#endif
+
+
+#ifdef DEBUG
+/**
+ * Dump a blob in hex to the same place that debug_printf sends its
+ * messages.
+ */
+void debug_print_blob( const char *name, const void *blob, unsigned size );
+
+/* Print a message along with a prettified format string
+ */
+void debug_print_format(const char *msg, unsigned fmt );
+#else
+#define debug_print_blob(_name, _blob, _size) ((void)0)
+#define debug_print_format(_msg, _fmt) ((void)0)
+#endif
+
+
+/**
+ * Hard-coded breakpoint.
+ */
+#ifdef DEBUG
+#define debug_break() os_break()
+#else /* !DEBUG */
+#define debug_break() ((void)0)
+#endif /* !DEBUG */
+
+
+long
+debug_get_num_option(const char *name, long dfault);
+
+void _debug_assert_fail(const char *expr,
+ const char *file,
+ unsigned line,
+ const char *function);
+
+
+/**
+ * Assert macro
+ *
+ * Do not expect that the assert call terminates -- errors must be handled
+ * regardless of assert behavior.
+ *
+ * For non debug builds the assert macro will expand to a no-op, so do not
+ * call functions with side effects in the assert expression.
+ */
+#ifdef DEBUG
+#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
+#else
+#define debug_assert(expr) do { } while (0 && (expr))
+#endif
+
+
+/** Override standard assert macro */
+#ifdef assert
+#undef assert
+#endif
+#define assert(expr) debug_assert(expr)
+
+
+/**
+ * Output the current function name.
+ */
+#ifdef DEBUG
+#define debug_checkpoint() \
+ _debug_printf("%s\n", __FUNCTION__)
+#else
+#define debug_checkpoint() \
+ ((void)0)
+#endif
+
+
+/**
+ * Output the full source code position.
+ */
+#ifdef DEBUG
+#define debug_checkpoint_full() \
+ _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__)
+#else
+#define debug_checkpoint_full() \
+ ((void)0)
+#endif
+
+
+/**
+ * Output a warning message. Muted on release version.
+ */
+#ifdef DEBUG
+#define debug_warning(__msg) \
+ _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
+#else
+#define debug_warning(__msg) \
+ ((void)0)
+#endif
+
+
+/**
+ * Output an error message. Not muted on release version.
+ */
+#ifdef DEBUG
+#define debug_error(__msg) \
+ _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
+#else
+#define debug_error(__msg) \
+ _debug_printf("error: %s\n", __msg)
+#endif
+
+
+/**
+ * Used by debug_dump_enum and debug_dump_flags to describe symbols.
+ */
+struct debug_named_value
+{
+ const char *name;
+ unsigned long value;
+ const char *desc;
+};
+
+
+/**
+ * Some C pre-processor magic to simplify creating named values.
+ *
+ * Example:
+ * @code
+ * static const debug_named_value my_names[] = {
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
+ * DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
+ * DEBUG_NAMED_VALUE_END
+ * };
+ *
+ * ...
+ * debug_printf("%s = %s\n",
+ * name,
+ * debug_dump_enum(my_names, my_value));
+ * ...
+ * @endcode
+ */
+#define DEBUG_NAMED_VALUE(__symbol) DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, NULL)
+#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
+#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
+
+
+/**
+ * Convert a enum value to a string.
+ */
+const char *
+debug_dump_enum(const struct debug_named_value *names,
+ unsigned long value);
+
+const char *
+debug_dump_enum_noprefix(const struct debug_named_value *names,
+ const char *prefix,
+ unsigned long value);
+
+
+/**
+ * Convert binary flags value to a string.
+ */
+const char *
+debug_dump_flags(const struct debug_named_value *names,
+ unsigned long value);
+
+
+/**
+ * Function enter exit loggers
+ */
+#ifdef DEBUG
+int debug_funclog_enter(const char* f, const int line, const char* file);
+void debug_funclog_exit(const char* f, const int line, const char* file);
+void debug_funclog_enter_exit(const char* f, const int line, const char* file);
+
+#define DEBUG_FUNCLOG_ENTER() \
+ int __debug_decleration_work_around = \
+ debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
+#define DEBUG_FUNCLOG_EXIT() \
+ do { \
+ (void)__debug_decleration_work_around; \
+ debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
+ return; \
+ } while(0)
+#define DEBUG_FUNCLOG_EXIT_RET(ret) \
+ do { \
+ (void)__debug_decleration_work_around; \
+ debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
+ return ret; \
+ } while(0)
+#define DEBUG_FUNCLOG_ENTER_EXIT() \
+ debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
+
+#else
+#define DEBUG_FUNCLOG_ENTER() \
+ int __debug_decleration_work_around
+#define DEBUG_FUNCLOG_EXIT() \
+ do { (void)__debug_decleration_work_around; return; } while(0)
+#define DEBUG_FUNCLOG_EXIT_RET(ret) \
+ do { (void)__debug_decleration_work_around; return ret; } while(0)
+#define DEBUG_FUNCLOG_ENTER_EXIT()
+#endif
+
+
+/**
+ * Get option.
+ *
+ * It is an alias for getenv on Linux.
+ *
+ * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
+ * endings with one option per line as
+ *
+ * NAME=value
+ *
+ * This file must be terminated with an extra empty line.
+ */
+const char *
+debug_get_option(const char *name, const char *dfault);
+
+boolean
+debug_get_bool_option(const char *name, boolean dfault);
+
+long
+debug_get_num_option(const char *name, long dfault);
+
+unsigned long
+debug_get_flags_option(const char *name,
+ const struct debug_named_value *flags,
+ unsigned long dfault);
+
+#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
+static boolean \
+debug_get_option_ ## sufix (void) \
+{ \
+ static boolean first = TRUE; \
+ static boolean value; \
+ if (first) { \
+ first = FALSE; \
+ value = debug_get_bool_option(name, dfault); \
+ } \
+ return value; \
+}
+
+#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
+static long \
+debug_get_option_ ## sufix (void) \
+{ \
+ static boolean first = TRUE; \
+ static long value; \
+ if (first) { \
+ first = FALSE; \
+ value = debug_get_num_option(name, dfault); \
+ } \
+ return value; \
+}
+
+#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
+static unsigned long \
+debug_get_option_ ## sufix (void) \
+{ \
+ static boolean first = TRUE; \
+ static unsigned long value; \
+ if (first) { \
+ first = FALSE; \
+ value = debug_get_flags_option(name, flags, dfault); \
+ } \
+ return value; \
+}
+
+
+unsigned long
+debug_memory_begin(void);
+
+void
+debug_memory_end(unsigned long beginning);
+
+
+#ifdef DEBUG
+struct pipe_context;
+struct pipe_surface;
+struct pipe_transfer;
+struct pipe_resource;
+
+void debug_dump_image(const char *prefix,
+ unsigned format, unsigned cpp,
+ unsigned width, unsigned height,
+ unsigned stride,
+ const void *data);
+void debug_dump_surface(struct pipe_context *pipe,
+ const char *prefix,
+ struct pipe_surface *surface);
+void debug_dump_texture(struct pipe_context *pipe,
+ const char *prefix,
+ struct pipe_resource *texture);
+void debug_dump_surface_bmp(struct pipe_context *pipe,
+ const char *filename,
+ struct pipe_surface *surface);
+void debug_dump_transfer_bmp(struct pipe_context *pipe,
+ const char *filename,
+ struct pipe_transfer *transfer);
+void debug_dump_float_rgba_bmp(const char *filename,
+ unsigned width, unsigned height,
+ float *rgba, unsigned stride);
+#else
+#define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0)
+#define debug_dump_surface(pipe, prefix, surface) ((void)0)
+#define debug_dump_surface_bmp(pipe, filename, surface) ((void)0)
+#define debug_dump_transfer_bmp(filename, transfer) ((void)0)
+#define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0)
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_H_ */
diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
index 64424f776..5b9e20374 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c
@@ -270,7 +270,8 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
break;
case PIPE_FORMAT_R16G16B16A16_SNORM:
- strb->Base.InternalFormat = GL_RGBA16;
+ /* accum buffer */
+ strb->Base.InternalFormat = GL_RGBA16_SNORM;
break;
case PIPE_FORMAT_R8_UNORM:
strb->Base.InternalFormat = GL_R8;
diff --git a/xorg-server/randr/rrcrtc.c b/xorg-server/randr/rrcrtc.c
index 23719f816..0437795c4 100644
--- a/xorg-server/randr/rrcrtc.c
+++ b/xorg-server/randr/rrcrtc.c
@@ -1,1506 +1,1506 @@
-/*
- * Copyright © 2006 Keith Packard
- * Copyright 2010 Red Hat, Inc
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#include "randrstr.h"
-#include "swaprep.h"
-#include "mipointer.h"
-
-RESTYPE RRCrtcType;
-
-/*
- * Notify the CRTC of some change
- */
-void
-RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
-{
- ScreenPtr pScreen = crtc->pScreen;
-
- crtc->changed = TRUE;
- if (pScreen)
- {
- rrScrPriv(pScreen);
-
- pScrPriv->changed = TRUE;
- /*
- * Send ConfigureNotify on any layout change
- */
- if (layoutChanged)
- pScrPriv->layoutChanged = TRUE;
- }
-}
-
-/*
- * Create a CRTC
- */
-RRCrtcPtr
-RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
-{
- RRCrtcPtr crtc;
- RRCrtcPtr *crtcs;
- rrScrPrivPtr pScrPriv;
-
- if (!RRInit())
- return NULL;
-
- pScrPriv = rrGetScrPriv(pScreen);
-
- /* make space for the crtc pointer */
- if (pScrPriv->numCrtcs)
- crtcs = realloc(pScrPriv->crtcs,
- (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
- else
- crtcs = malloc(sizeof (RRCrtcPtr));
- if (!crtcs)
- return FALSE;
- pScrPriv->crtcs = crtcs;
-
- crtc = calloc(1, sizeof (RRCrtcRec));
- if (!crtc)
- return NULL;
- crtc->id = FakeClientID (0);
- crtc->pScreen = pScreen;
- crtc->mode = NULL;
- crtc->x = 0;
- crtc->y = 0;
- crtc->rotation = RR_Rotate_0;
- crtc->rotations = RR_Rotate_0;
- crtc->outputs = NULL;
- crtc->numOutputs = 0;
- crtc->gammaSize = 0;
- crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
- crtc->changed = FALSE;
- crtc->devPrivate = devPrivate;
- RRTransformInit (&crtc->client_pending_transform);
- RRTransformInit (&crtc->client_current_transform);
- pixman_transform_init_identity (&crtc->transform);
- pixman_f_transform_init_identity (&crtc->f_transform);
- pixman_f_transform_init_identity (&crtc->f_inverse);
-
- if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
- return NULL;
-
- /* attach the screen and crtc together */
- crtc->pScreen = pScreen;
- pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
-
- return crtc;
-}
-
-/*
- * Set the allowed rotations on a CRTC
- */
-void
-RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
-{
- crtc->rotations = rotations;
-}
-
-/*
- * Set whether transforms are allowed on a CRTC
- */
-void
-RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms)
-{
- crtc->transforms = transforms;
-}
-
-/*
- * Notify the extension that the Crtc has been reconfigured,
- * the driver calls this whenever it has updated the mode
- */
-Bool
-RRCrtcNotify (RRCrtcPtr crtc,
- RRModePtr mode,
- int x,
- int y,
- Rotation rotation,
- RRTransformPtr transform,
- int numOutputs,
- RROutputPtr *outputs)
-{
- int i, j;
-
- /*
- * Check to see if any of the new outputs were
- * not in the old list and mark them as changed
- */
- for (i = 0; i < numOutputs; i++)
- {
- for (j = 0; j < crtc->numOutputs; j++)
- if (outputs[i] == crtc->outputs[j])
- break;
- if (j == crtc->numOutputs)
- {
- outputs[i]->crtc = crtc;
- RROutputChanged (outputs[i], FALSE);
- RRCrtcChanged (crtc, FALSE);
- }
- }
- /*
- * Check to see if any of the old outputs are
- * not in the new list and mark them as changed
- */
- for (j = 0; j < crtc->numOutputs; j++)
- {
- for (i = 0; i < numOutputs; i++)
- if (outputs[i] == crtc->outputs[j])
- break;
- if (i == numOutputs)
- {
- if (crtc->outputs[j]->crtc == crtc)
- crtc->outputs[j]->crtc = NULL;
- RROutputChanged (crtc->outputs[j], FALSE);
- RRCrtcChanged (crtc, FALSE);
- }
- }
- /*
- * Reallocate the crtc output array if necessary
- */
- if (numOutputs != crtc->numOutputs)
- {
- RROutputPtr *newoutputs;
-
- if (numOutputs)
- {
- if (crtc->numOutputs)
- newoutputs = realloc(crtc->outputs,
- numOutputs * sizeof (RROutputPtr));
- else
- newoutputs = malloc(numOutputs * sizeof (RROutputPtr));
- if (!newoutputs)
- return FALSE;
- }
- else
- {
- free(crtc->outputs);
- newoutputs = NULL;
- }
- crtc->outputs = newoutputs;
- crtc->numOutputs = numOutputs;
- }
- /*
- * Copy the new list of outputs into the crtc
- */
- memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr));
- /*
- * Update remaining crtc fields
- */
- if (mode != crtc->mode)
- {
- if (crtc->mode)
- RRModeDestroy (crtc->mode);
- crtc->mode = mode;
- if (mode != NULL)
- mode->refcnt++;
- RRCrtcChanged (crtc, TRUE);
- }
- if (x != crtc->x)
- {
- crtc->x = x;
- RRCrtcChanged (crtc, TRUE);
- }
- if (y != crtc->y)
- {
- crtc->y = y;
- RRCrtcChanged (crtc, TRUE);
- }
- if (rotation != crtc->rotation)
- {
- crtc->rotation = rotation;
- RRCrtcChanged (crtc, TRUE);
- }
- if (!RRTransformEqual (transform, &crtc->client_current_transform)) {
- RRTransformCopy (&crtc->client_current_transform, transform);
- RRCrtcChanged (crtc, TRUE);
- }
- if (crtc->changed && mode)
- {
- RRTransformCompute (x, y,
- mode->mode.width, mode->mode.height,
- rotation,
- &crtc->client_current_transform,
- &crtc->transform, &crtc->f_transform,
- &crtc->f_inverse);
- }
- return TRUE;
-}
-
-void
-RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- rrScrPriv (pScreen);
- xRRCrtcChangeNotifyEvent ce;
- RRModePtr mode = crtc->mode;
-
- ce.type = RRNotify + RREventBase;
- ce.subCode = RRNotify_CrtcChange;
- ce.timestamp = pScrPriv->lastSetTime.milliseconds;
- ce.window = pWin->drawable.id;
- ce.crtc = crtc->id;
- ce.rotation = crtc->rotation;
- if (mode)
- {
- ce.mode = mode->mode.id;
- ce.x = crtc->x;
- ce.y = crtc->y;
- ce.width = mode->mode.width;
- ce.height = mode->mode.height;
- }
- else
- {
- ce.mode = None;
- ce.x = 0;
- ce.y = 0;
- ce.width = 0;
- ce.height = 0;
- }
- WriteEventsToClient (client, 1, (xEvent *) &ce);
-}
-
-static Bool
-RRCrtcPendingProperties (RRCrtcPtr crtc)
-{
- ScreenPtr pScreen = crtc->pScreen;
- rrScrPriv(pScreen);
- int o;
-
- for (o = 0; o < pScrPriv->numOutputs; o++)
- {
- RROutputPtr output = pScrPriv->outputs[o];
- if (output->crtc == crtc && output->pendingProperties)
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom)
-{
- *left = crtc->x;
- *top = crtc->y;
-
- switch (crtc->rotation) {
- case RR_Rotate_0:
- case RR_Rotate_180:
- default:
- *right = crtc->x + crtc->mode->mode.width;
- *bottom = crtc->y + crtc->mode->mode.height;
- return;
- case RR_Rotate_90:
- case RR_Rotate_270:
- *right = crtc->x + crtc->mode->mode.height;
- *bottom = crtc->y + crtc->mode->mode.width;
- return;
- }
-}
-
-/* overlapping counts as adjacent */
-static Bool
-crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b)
-{
- /* left, right, top, bottom... */
- int al, ar, at, ab;
- int bl, br, bt, bb;
- int cl, cr, ct, cb; /* the overlap, if any */
-
- crtc_bounds(a, &al, &ar, &at, &ab);
- crtc_bounds(b, &bl, &br, &bt, &bb);
-
- cl = max(al, bl);
- cr = min(ar, br);
- ct = max(at, bt);
- cb = min(ab, bb);
-
- return (cl <= cr) && (ct <= cb);
-}
-
-/* Depth-first search and mark all CRTCs reachable from cur */
-static void
-mark_crtcs (rrScrPrivPtr pScrPriv, int *reachable, int cur)
-{
- int i;
- reachable[cur] = TRUE;
- for (i = 0; i < pScrPriv->numCrtcs; ++i) {
- if (reachable[i] || !pScrPriv->crtcs[i]->mode)
- continue;
- if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i]))
- mark_crtcs(pScrPriv, reachable, i);
- }
-}
-
-static void
-RRComputeContiguity (ScreenPtr pScreen)
-{
- rrScrPriv(pScreen);
- Bool discontiguous = TRUE;
- int i, n = pScrPriv->numCrtcs;
-
- int *reachable = calloc(n, sizeof(int));
- if (!reachable)
- goto out;
-
- /* Find first enabled CRTC and start search for reachable CRTCs from it */
- for (i = 0; i < n; ++i) {
- if (pScrPriv->crtcs[i]->mode) {
- mark_crtcs(pScrPriv, reachable, i);
- break;
- }
- }
-
- /* Check that all enabled CRTCs were marked as reachable */
- for (i = 0; i < n; ++i)
- if (pScrPriv->crtcs[i]->mode && !reachable[i])
- goto out;
-
- discontiguous = FALSE;
-
-out:
- free(reachable);
- pScrPriv->discontiguous = discontiguous;
-}
-
-/*
- * Request that the Crtc be reconfigured
- */
-Bool
-RRCrtcSet (RRCrtcPtr crtc,
- RRModePtr mode,
- int x,
- int y,
- Rotation rotation,
- int numOutputs,
- RROutputPtr *outputs)
-{
- ScreenPtr pScreen = crtc->pScreen;
- Bool ret = FALSE;
- Bool recompute = TRUE;
- rrScrPriv(pScreen);
-
- /* See if nothing changed */
- if (crtc->mode == mode &&
- crtc->x == x &&
- crtc->y == y &&
- crtc->rotation == rotation &&
- crtc->numOutputs == numOutputs &&
- !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
- !RRCrtcPendingProperties (crtc) &&
- !RRCrtcPendingTransform (crtc))
- {
- recompute = FALSE;
- ret = TRUE;
- }
- else
- {
-#if RANDR_12_INTERFACE
- if (pScrPriv->rrCrtcSet)
- {
- ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
- rotation, numOutputs, outputs);
- }
- else
-#endif
- {
-#if RANDR_10_INTERFACE
- if (pScrPriv->rrSetConfig)
- {
- RRScreenSize size;
- RRScreenRate rate;
-
- if (!mode)
- {
- RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL);
- ret = TRUE;
- }
- else
- {
- size.width = mode->mode.width;
- size.height = mode->mode.height;
- if (outputs[0]->mmWidth && outputs[0]->mmHeight)
- {
- size.mmWidth = outputs[0]->mmWidth;
- size.mmHeight = outputs[0]->mmHeight;
- }
- else
- {
- size.mmWidth = pScreen->mmWidth;
- size.mmHeight = pScreen->mmHeight;
- }
- size.nRates = 1;
- rate.rate = RRVerticalRefresh (&mode->mode);
- size.pRates = &rate;
- ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
- /*
- * Old 1.0 interface tied screen size to mode size
- */
- if (ret)
- {
- RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs);
- RRScreenSizeNotify (pScreen);
- }
- }
- }
-#endif
- }
- if (ret)
- {
- int o;
- RRTellChanged (pScreen);
-
- for (o = 0; o < numOutputs; o++)
- RRPostPendingProperties (outputs[o]);
- }
- }
-
- if (recompute)
- RRComputeContiguity(pScreen);
-
- return ret;
-}
-
-/*
- * Return crtc transform
- */
-RRTransformPtr
-RRCrtcGetTransform (RRCrtcPtr crtc)
-{
- RRTransformPtr transform = &crtc->client_pending_transform;
-
- if (pixman_transform_is_identity (&transform->transform))
- return NULL;
- return transform;
-}
-
-/*
- * Check whether the pending and current transforms are the same
- */
-Bool
-RRCrtcPendingTransform (RRCrtcPtr crtc)
-{
- return memcmp (&crtc->client_current_transform.transform,
- &crtc->client_pending_transform.transform,
- sizeof (PictTransform)) != 0;
-}
-
-/*
- * Destroy a Crtc at shutdown
- */
-void
-RRCrtcDestroy (RRCrtcPtr crtc)
-{
- FreeResource (crtc->id, 0);
-}
-
-static int
-RRCrtcDestroyResource (pointer value, XID pid)
-{
- RRCrtcPtr crtc = (RRCrtcPtr) value;
- ScreenPtr pScreen = crtc->pScreen;
-
- if (pScreen)
- {
- rrScrPriv(pScreen);
- int i;
-
- for (i = 0; i < pScrPriv->numCrtcs; i++)
- {
- if (pScrPriv->crtcs[i] == crtc)
- {
- memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
- (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr));
- --pScrPriv->numCrtcs;
- break;
- }
- }
- }
- free(crtc->gammaRed);
- if (crtc->mode)
- RRModeDestroy (crtc->mode);
- free(crtc);
- return 1;
-}
-
-/*
- * Request that the Crtc gamma be changed
- */
-
-Bool
-RRCrtcGammaSet (RRCrtcPtr crtc,
- CARD16 *red,
- CARD16 *green,
- CARD16 *blue)
-{
- Bool ret = TRUE;
-#if RANDR_12_INTERFACE
- ScreenPtr pScreen = crtc->pScreen;
-#endif
-
- memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16));
- memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16));
- memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16));
-#if RANDR_12_INTERFACE
- if (pScreen)
- {
- rrScrPriv(pScreen);
- if (pScrPriv->rrCrtcSetGamma)
- ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
- }
-#endif
- return ret;
-}
-
-/*
- * Request current gamma back from the DDX (if possible).
- * This includes gamma size.
- */
-Bool
-RRCrtcGammaGet(RRCrtcPtr crtc)
-{
- Bool ret = TRUE;
-#if RANDR_12_INTERFACE
- ScreenPtr pScreen = crtc->pScreen;
-#endif
-
-#if RANDR_12_INTERFACE
- if (pScreen)
- {
- rrScrPriv(pScreen);
- if (pScrPriv->rrCrtcGetGamma)
- ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc);
- }
-#endif
- return ret;
-}
-
-/*
- * Notify the extension that the Crtc gamma has been changed
- * The driver calls this whenever it has changed the gamma values
- * in the RRCrtcRec
- */
-
-Bool
-RRCrtcGammaNotify (RRCrtcPtr crtc)
-{
- return TRUE; /* not much going on here */
-}
-
-static void
-RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
- int *width, int *height)
-{
- BoxRec box;
-
- if (mode == NULL) {
- *width = 0;
- *height = 0;
- return;
- }
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = mode->mode.width;
- box.y2 = mode->mode.height;
-
- pixman_transform_bounds (transform, &box);
- *width = box.x2 - box.x1;
- *height = box.y2 - box.y1;
-}
-
-/**
- * Returns the width/height that the crtc scans out from the framebuffer
- */
-void
-RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
-{
- RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height);
-}
-
-/*
- * Set the size of the gamma table at server startup time
- */
-
-Bool
-RRCrtcGammaSetSize (RRCrtcPtr crtc,
- int size)
-{
- CARD16 *gamma;
-
- if (size == crtc->gammaSize)
- return TRUE;
- if (size)
- {
- gamma = malloc(size * 3 * sizeof (CARD16));
- if (!gamma)
- return FALSE;
- }
- else
- gamma = NULL;
- free(crtc->gammaRed);
- crtc->gammaRed = gamma;
- crtc->gammaGreen = gamma + size;
- crtc->gammaBlue = gamma + size*2;
- crtc->gammaSize = size;
- return TRUE;
-}
-
-/*
- * Set the pending CRTC transformation
- */
-
-int
-RRCrtcTransformSet (RRCrtcPtr crtc,
- PictTransformPtr transform,
- struct pixman_f_transform *f_transform,
- struct pixman_f_transform *f_inverse,
- char *filter_name,
- int filter_len,
- xFixed *params,
- int nparams)
-{
- PictFilterPtr filter = NULL;
- int width = 0, height = 0;
-
- if (!crtc->transforms)
- return BadValue;
-
- if (filter_len)
- {
- filter = PictureFindFilter (crtc->pScreen,
- filter_name,
- filter_len);
- if (!filter)
- return BadName;
- if (filter->ValidateParams)
- {
- if (!filter->ValidateParams (crtc->pScreen, filter->id,
- params, nparams, &width, &height))
- return BadMatch;
- }
- else {
- width = filter->width;
- height = filter->height;
- }
- }
- else
- {
- if (nparams)
- return BadMatch;
- }
- if (!RRTransformSetFilter (&crtc->client_pending_transform,
- filter, params, nparams, width, height))
- return BadAlloc;
-
- crtc->client_pending_transform.transform = *transform;
- crtc->client_pending_transform.f_transform = *f_transform;
- crtc->client_pending_transform.f_inverse = *f_inverse;
- return Success;
-}
-
-/*
- * Initialize crtc type
- */
-Bool
-RRCrtcInit (void)
-{
- RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC");
- if (!RRCrtcType)
- return FALSE;
-
- return TRUE;
-}
-
-/*
- * Initialize crtc type error value
- */
-void
-RRCrtcInitErrorValue(void)
-{
- SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc);
-}
-
-int
-ProcRRGetCrtcInfo (ClientPtr client)
-{
- REQUEST(xRRGetCrtcInfoReq);
- xRRGetCrtcInfoReply rep;
- RRCrtcPtr crtc;
- CARD8 *extra;
- unsigned long extraLen;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- RRModePtr mode;
- RROutput *outputs;
- RROutput *possible;
- int i, j, k, n;
- int width, height;
- BoxRec panned_area;
-
- REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-
- /* All crtcs must be associated with screens before client
- * requests are processed
- */
- pScreen = crtc->pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
-
- mode = crtc->mode;
-
- rep.type = X_Reply;
- rep.status = RRSetConfigSuccess;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.timestamp = pScrPriv->lastSetTime.milliseconds;
- if (pScrPriv->rrGetPanning &&
- pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) &&
- (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1))
- {
- rep.x = panned_area.x1;
- rep.y = panned_area.y1;
- rep.width = panned_area.x2 - panned_area.x1;
- rep.height = panned_area.y2 - panned_area.y1;
- }
- else
- {
- RRCrtcGetScanoutSize (crtc, &width, &height);
- rep.x = crtc->x;
- rep.y = crtc->y;
- rep.width = width;
- rep.height = height;
- }
- rep.mode = mode ? mode->mode.id : 0;
- rep.rotation = crtc->rotation;
- rep.rotations = crtc->rotations;
- rep.nOutput = crtc->numOutputs;
- k = 0;
- for (i = 0; i < pScrPriv->numOutputs; i++)
- for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
- if (pScrPriv->outputs[i]->crtcs[j] == crtc)
- k++;
- rep.nPossibleOutput = k;
-
- rep.length = rep.nOutput + rep.nPossibleOutput;
-
- extraLen = rep.length << 2;
- if (extraLen)
- {
- extra = malloc(extraLen);
- if (!extra)
- return BadAlloc;
- }
- else
- extra = NULL;
-
- outputs = (RROutput *) extra;
- possible = (RROutput *) (outputs + rep.nOutput);
-
- for (i = 0; i < crtc->numOutputs; i++)
- {
- outputs[i] = crtc->outputs[i]->id;
- if (client->swapped)
- swapl (&outputs[i], n);
- }
- k = 0;
- for (i = 0; i < pScrPriv->numOutputs; i++)
- for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
- if (pScrPriv->outputs[i]->crtcs[j] == crtc)
- {
- possible[k] = pScrPriv->outputs[i]->id;
- if (client->swapped)
- swapl (&possible[k], n);
- k++;
- }
-
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.timestamp, n);
- swaps(&rep.x, n);
- swaps(&rep.y, n);
- swaps(&rep.width, n);
- swaps(&rep.height, n);
- swapl(&rep.mode, n);
- swaps(&rep.rotation, n);
- swaps(&rep.rotations, n);
- swaps(&rep.nOutput, n);
- swaps(&rep.nPossibleOutput, n);
- }
- WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep);
- if (extraLen)
- {
- WriteToClient (client, extraLen, (char *) extra);
- free(extra);
- }
-
- return Success;
-}
-
-int
-ProcRRSetCrtcConfig (ClientPtr client)
-{
- REQUEST(xRRSetCrtcConfigReq);
- xRRSetCrtcConfigReply rep;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- RRCrtcPtr crtc;
- RRModePtr mode;
- int numOutputs;
- RROutputPtr *outputs = NULL;
- RROutput *outputIds;
- TimeStamp configTime;
- TimeStamp time;
- Rotation rotation;
- int rc, i, j;
-
- REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
- numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq)));
-
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess);
-
- if (stuff->mode == None)
- {
- mode = NULL;
- if (numOutputs > 0)
- return BadMatch;
- }
- else
- {
- VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess);
- if (numOutputs == 0)
- return BadMatch;
- }
- if (numOutputs)
- {
- outputs = malloc(numOutputs * sizeof (RROutputPtr));
- if (!outputs)
- return BadAlloc;
- }
- else
- outputs = NULL;
-
- outputIds = (RROutput *) (stuff + 1);
- for (i = 0; i < numOutputs; i++)
- {
- rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i],
- RROutputType, client, DixSetAttrAccess);
- if (rc != Success)
- {
- free(outputs);
- return rc;
- }
- /* validate crtc for this output */
- for (j = 0; j < outputs[i]->numCrtcs; j++)
- if (outputs[i]->crtcs[j] == crtc)
- break;
- if (j == outputs[i]->numCrtcs)
- {
- free(outputs);
- return BadMatch;
- }
- /* validate mode for this output */
- for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
- {
- RRModePtr m = (j < outputs[i]->numModes ?
- outputs[i]->modes[j] :
- outputs[i]->userModes[j - outputs[i]->numModes]);
- if (m == mode)
- break;
- }
- if (j == outputs[i]->numModes + outputs[i]->numUserModes)
- {
- free(outputs);
- return BadMatch;
- }
- }
- /* validate clones */
- for (i = 0; i < numOutputs; i++)
- {
- for (j = 0; j < numOutputs; j++)
- {
- int k;
- if (i == j)
- continue;
- for (k = 0; k < outputs[i]->numClones; k++)
- {
- if (outputs[i]->clones[k] == outputs[j])
- break;
- }
- if (k == outputs[i]->numClones)
- {
- free(outputs);
- return BadMatch;
- }
- }
- }
-
- pScreen = crtc->pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
-
- time = ClientTimeToServerTime(stuff->timestamp);
- configTime = ClientTimeToServerTime(stuff->configTimestamp);
-
- if (!pScrPriv)
- {
- time = currentTime;
- rep.status = RRSetConfigFailed;
- goto sendReply;
- }
-
- /*
- * Validate requested rotation
- */
- rotation = (Rotation) stuff->rotation;
-
- /* test the rotation bits only! */
- switch (rotation & 0xf) {
- case RR_Rotate_0:
- case RR_Rotate_90:
- case RR_Rotate_180:
- case RR_Rotate_270:
- break;
- default:
- /*
- * Invalid rotation
- */
- client->errorValue = stuff->rotation;
- free(outputs);
- return BadValue;
- }
-
- if (mode)
- {
- if ((~crtc->rotations) & rotation)
- {
- /*
- * requested rotation or reflection not supported by screen
- */
- client->errorValue = stuff->rotation;
- free(outputs);
- return BadMatch;
- }
-
-#ifdef RANDR_12_INTERFACE
- /*
- * Check screen size bounds if the DDX provides a 1.2 interface
- * for setting screen size. Else, assume the CrtcSet sets
- * the size along with the mode. If the driver supports transforms,
- * then it must allow crtcs to display a subset of the screen, so
- * only do this check for drivers without transform support.
- */
- if (pScrPriv->rrScreenSetSize && !crtc->transforms)
- {
- int source_width;
- int source_height;
- PictTransform transform;
- struct pixman_f_transform f_transform, f_inverse;
-
- RRTransformCompute (stuff->x, stuff->y,
- mode->mode.width, mode->mode.height,
- rotation,
- &crtc->client_pending_transform,
- &transform, &f_transform, &f_inverse);
-
- RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
- if (stuff->x + source_width > pScreen->width)
- {
- client->errorValue = stuff->x;
- free(outputs);
- return BadValue;
- }
-
- if (stuff->y + source_height > pScreen->height)
- {
- client->errorValue = stuff->y;
- free(outputs);
- return BadValue;
- }
- }
-#endif
- }
-
- if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
- rotation, numOutputs, outputs))
- {
- rep.status = RRSetConfigFailed;
- goto sendReply;
- }
- rep.status = RRSetConfigSuccess;
- pScrPriv->lastSetTime = time;
-
-sendReply:
- free(outputs);
-
- rep.type = X_Reply;
- /* rep.status has already been filled in */
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
-
- if (client->swapped)
- {
- int n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.newTimestamp, n);
- }
- WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep);
-
- return Success;
-}
-
-int
-ProcRRGetPanning (ClientPtr client)
-{
- REQUEST(xRRGetPanningReq);
- xRRGetPanningReply rep;
- RRCrtcPtr crtc;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- BoxRec total;
- BoxRec tracking;
- INT16 border[4];
- int n;
-
- REQUEST_SIZE_MATCH(xRRGetPanningReq);
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-
- /* All crtcs must be associated with screens before client
- * requests are processed
- */
- pScreen = crtc->pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
-
- if (!pScrPriv)
- return RRErrorBase + BadRRCrtc;
-
- memset(&rep, 0, sizeof(rep));
- rep.type = X_Reply;
- rep.status = RRSetConfigSuccess;
- rep.sequenceNumber = client->sequence;
- rep.length = 1;
- rep.timestamp = pScrPriv->lastSetTime.milliseconds;
-
- if (pScrPriv->rrGetPanning &&
- pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) {
- rep.left = total.x1;
- rep.top = total.y1;
- rep.width = total.x2 - total.x1;
- rep.height = total.y2 - total.y1;
- rep.track_left = tracking.x1;
- rep.track_top = tracking.y1;
- rep.track_width = tracking.x2 - tracking.x1;
- rep.track_height = tracking.y2 - tracking.y1;
- rep.border_left = border[0];
- rep.border_top = border[1];
- rep.border_right = border[2];
- rep.border_bottom = border[3];
- }
-
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swaps(&rep.timestamp, n);
- swaps(&rep.left, n);
- swaps(&rep.top, n);
- swaps(&rep.width, n);
- swaps(&rep.height, n);
- swaps(&rep.track_left, n);
- swaps(&rep.track_top, n);
- swaps(&rep.track_width, n);
- swaps(&rep.track_height, n);
- swaps(&rep.border_left, n);
- swaps(&rep.border_top, n);
- swaps(&rep.border_right, n);
- swaps(&rep.border_bottom, n);
- }
- WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep);
- return Success;
-}
-
-int
-ProcRRSetPanning (ClientPtr client)
-{
- REQUEST(xRRSetPanningReq);
- xRRSetPanningReply rep;
- RRCrtcPtr crtc;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- TimeStamp time;
- BoxRec total;
- BoxRec tracking;
- INT16 border[4];
- int n;
-
- REQUEST_SIZE_MATCH(xRRSetPanningReq);
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-
- /* All crtcs must be associated with screens before client
- * requests are processed
- */
- pScreen = crtc->pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
-
- if (!pScrPriv) {
- time = currentTime;
- rep.status = RRSetConfigFailed;
- goto sendReply;
- }
-
- time = ClientTimeToServerTime(stuff->timestamp);
-
- if (!pScrPriv->rrGetPanning)
- return RRErrorBase + BadRRCrtc;
-
- total.x1 = stuff->left;
- total.y1 = stuff->top;
- total.x2 = total.x1 + stuff->width;
- total.y2 = total.y1 + stuff->height;
- tracking.x1 = stuff->track_left;
- tracking.y1 = stuff->track_top;
- tracking.x2 = tracking.x1 + stuff->track_width;
- tracking.y2 = tracking.y1 + stuff->track_height;
- border[0] = stuff->border_left;
- border[1] = stuff->border_top;
- border[2] = stuff->border_right;
- border[3] = stuff->border_bottom;
-
- if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border))
- return BadMatch;
-
- pScrPriv->lastSetTime = time;
-
- rep.status = RRSetConfigSuccess;
-
-sendReply:
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
-
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swaps(&rep.newTimestamp, n);
- }
- WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep);
- return Success;
-}
-
-int
-ProcRRGetCrtcGammaSize (ClientPtr client)
-{
- REQUEST(xRRGetCrtcGammaSizeReq);
- xRRGetCrtcGammaSizeReply reply;
- RRCrtcPtr crtc;
- int n;
-
- REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-
- /* Gamma retrieval failed, any better error? */
- if (!RRCrtcGammaGet(crtc))
- return RRErrorBase + BadRRCrtc;
-
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.length = 0;
- reply.size = crtc->gammaSize;
- if (client->swapped) {
- swaps (&reply.sequenceNumber, n);
- swapl (&reply.length, n);
- swaps (&reply.size, n);
- }
- WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply);
- return Success;
-}
-
-int
-ProcRRGetCrtcGamma (ClientPtr client)
-{
- REQUEST(xRRGetCrtcGammaReq);
- xRRGetCrtcGammaReply reply;
- RRCrtcPtr crtc;
- int n;
- unsigned long len;
- char *extra = NULL;
-
- REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-
- /* Gamma retrieval failed, any better error? */
- if (!RRCrtcGammaGet(crtc))
- return RRErrorBase + BadRRCrtc;
-
- len = crtc->gammaSize * 3 * 2;
-
- if (crtc->gammaSize) {
- extra = malloc(len);
- if (!extra)
- return BadAlloc;
- }
-
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.length = bytes_to_int32(len);
- reply.size = crtc->gammaSize;
- if (client->swapped) {
- swaps (&reply.sequenceNumber, n);
- swapl (&reply.length, n);
- swaps (&reply.size, n);
- }
- WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply);
- if (crtc->gammaSize)
- {
- memcpy(extra, crtc->gammaRed, len);
- client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write;
- WriteSwappedDataToClient (client, len, extra);
- free(extra);
- }
- return Success;
-}
-
-int
-ProcRRSetCrtcGamma (ClientPtr client)
-{
- REQUEST(xRRSetCrtcGammaReq);
- RRCrtcPtr crtc;
- unsigned long len;
- CARD16 *red, *green, *blue;
-
- REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-
- len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq));
- if (len < (stuff->size * 3 + 1) >> 1)
- return BadLength;
-
- if (stuff->size != crtc->gammaSize)
- return BadMatch;
-
- red = (CARD16 *) (stuff + 1);
- green = red + crtc->gammaSize;
- blue = green + crtc->gammaSize;
-
- RRCrtcGammaSet (crtc, red, green, blue);
-
- return Success;
-}
-
-/* Version 1.3 additions */
-
-int
-ProcRRSetCrtcTransform (ClientPtr client)
-{
- REQUEST(xRRSetCrtcTransformReq);
- RRCrtcPtr crtc;
- PictTransform transform;
- struct pixman_f_transform f_transform, f_inverse;
- char *filter;
- int nbytes;
- xFixed *params;
- int nparams;
-
- REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq);
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-
- PictTransform_from_xRenderTransform (&transform, &stuff->transform);
- pixman_f_transform_from_pixman_transform (&f_transform, &transform);
- if (!pixman_f_transform_invert (&f_inverse, &f_transform))
- return BadMatch;
-
- filter = (char *) (stuff + 1);
- nbytes = stuff->nbytesFilter;
- params = (xFixed *) (filter + pad_to_int32(nbytes));
- nparams = ((xFixed *) stuff + client->req_len) - params;
- if (nparams < 0)
- return BadLength;
-
- return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse,
- filter, nbytes, params, nparams);
-}
-
-
-#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32)
-
-static int
-transform_filter_length (RRTransformPtr transform)
-{
- int nbytes, nparams;
-
- if (transform->filter == NULL)
- return 0;
- nbytes = strlen (transform->filter->name);
- nparams = transform->nparams;
- return pad_to_int32(nbytes) + (nparams * sizeof (xFixed));
-}
-
-static int
-transform_filter_encode (ClientPtr client, char *output,
- CARD16 *nbytesFilter,
- CARD16 *nparamsFilter,
- RRTransformPtr transform)
-{
- int nbytes, nparams;
- int n;
-
- if (transform->filter == NULL) {
- *nbytesFilter = 0;
- *nparamsFilter = 0;
- return 0;
- }
- nbytes = strlen (transform->filter->name);
- nparams = transform->nparams;
- *nbytesFilter = nbytes;
- *nparamsFilter = nparams;
- memcpy (output, transform->filter->name, nbytes);
- while ((nbytes & 3) != 0)
- output[nbytes++] = 0;
- memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed));
- if (client->swapped) {
- swaps (nbytesFilter, n);
- swaps (nparamsFilter, n);
- SwapLongs ((CARD32 *) (output + nbytes), nparams);
- }
- nbytes += nparams * sizeof (xFixed);
- return nbytes;
-}
-
-static void
-transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict)
-{
- xRenderTransform_from_PictTransform (wire, pict);
- if (client->swapped)
- SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform)));
-}
-
-int
-ProcRRGetCrtcTransform (ClientPtr client)
-{
- REQUEST(xRRGetCrtcTransformReq);
- xRRGetCrtcTransformReply *reply;
- RRCrtcPtr crtc;
- int n, nextra;
- RRTransformPtr current, pending;
- char *extra;
-
- REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq);
- VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-
- pending = &crtc->client_pending_transform;
- current = &crtc->client_current_transform;
-
- nextra = (transform_filter_length (pending) +
- transform_filter_length (current));
-
- reply = malloc(sizeof (xRRGetCrtcTransformReply) + nextra);
- if (!reply)
- return BadAlloc;
-
- extra = (char *) (reply + 1);
- reply->type = X_Reply;
- reply->sequenceNumber = client->sequence;
- reply->length = bytes_to_int32(CrtcTransformExtra + nextra);
-
- reply->hasTransforms = crtc->transforms;
-
- transform_encode (client, &reply->pendingTransform, &pending->transform);
- extra += transform_filter_encode (client, extra,
- &reply->pendingNbytesFilter,
- &reply->pendingNparamsFilter,
- pending);
-
- transform_encode (client, &reply->currentTransform, &current->transform);
- extra += transform_filter_encode (client, extra,
- &reply->currentNbytesFilter,
- &reply->currentNparamsFilter,
- current);
-
- if (client->swapped) {
- swaps (&reply->sequenceNumber, n);
- swapl (&reply->length, n);
- }
- WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply);
- free(reply);
- return Success;
-}
-
-void
-RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, int *y)
-{
- rrScrPriv (pScreen);
- int i;
-
- /* intentional dead space -> let it float */
- if (pScrPriv->discontiguous)
- return;
-
- /* if we're moving inside a crtc, we're fine */
- for (i = 0; i < pScrPriv->numCrtcs; i++) {
- RRCrtcPtr crtc = pScrPriv->crtcs[i];
-
- int left, right, top, bottom;
-
- if (!crtc->mode)
- continue;
-
- crtc_bounds(crtc, &left, &right, &top, &bottom);
-
- if ((*x >= left) && (*x <= right) && (*y >= top) && (*y <= bottom))
- return;
- }
-
- /* if we're trying to escape, clamp to the CRTC we're coming from */
- for (i = 0; i < pScrPriv->numCrtcs; i++) {
- RRCrtcPtr crtc = pScrPriv->crtcs[i];
- int nx, ny;
- int left, right, top, bottom;
-
- if (!crtc->mode)
- continue;
-
- crtc_bounds(crtc, &left, &right, &top, &bottom);
- miPointerGetPosition(pDev, &nx, &ny);
-
- if ((nx >= left) && (nx <= right) && (ny >= top) && (ny <= bottom)) {
- if ((*x <= left) || (*x >= right)) {
- int dx = *x - nx;
-
- if (dx > 0)
- *x = right;
- else if (dx < 0)
- *x = left;
- }
-
- if ((*y <= top) || (*y >= bottom)) {
- int dy = *y - ny;
-
- if (dy > 0)
- *y = bottom;
- else if (dy < 0)
- *y = top;
- }
-
- return;
- }
- }
-}
+/*
+ * Copyright © 2006 Keith Packard
+ * Copyright 2010 Red Hat, Inc
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+#include "swaprep.h"
+#include "mipointer.h"
+
+RESTYPE RRCrtcType;
+
+/*
+ * Notify the CRTC of some change
+ */
+void
+RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
+{
+ ScreenPtr pScreen = crtc->pScreen;
+
+ crtc->changed = TRUE;
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+
+ pScrPriv->changed = TRUE;
+ /*
+ * Send ConfigureNotify on any layout change
+ */
+ if (layoutChanged)
+ pScrPriv->layoutChanged = TRUE;
+ }
+}
+
+/*
+ * Create a CRTC
+ */
+RRCrtcPtr
+RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
+{
+ RRCrtcPtr crtc;
+ RRCrtcPtr *crtcs;
+ rrScrPrivPtr pScrPriv;
+
+ if (!RRInit())
+ return NULL;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ /* make space for the crtc pointer */
+ if (pScrPriv->numCrtcs)
+ crtcs = realloc(pScrPriv->crtcs,
+ (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
+ else
+ crtcs = malloc(sizeof (RRCrtcPtr));
+ if (!crtcs)
+ return FALSE;
+ pScrPriv->crtcs = crtcs;
+
+ crtc = calloc(1, sizeof (RRCrtcRec));
+ if (!crtc)
+ return NULL;
+ crtc->id = FakeClientID (0);
+ crtc->pScreen = pScreen;
+ crtc->mode = NULL;
+ crtc->x = 0;
+ crtc->y = 0;
+ crtc->rotation = RR_Rotate_0;
+ crtc->rotations = RR_Rotate_0;
+ crtc->outputs = NULL;
+ crtc->numOutputs = 0;
+ crtc->gammaSize = 0;
+ crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
+ crtc->changed = FALSE;
+ crtc->devPrivate = devPrivate;
+ RRTransformInit (&crtc->client_pending_transform);
+ RRTransformInit (&crtc->client_current_transform);
+ pixman_transform_init_identity (&crtc->transform);
+ pixman_f_transform_init_identity (&crtc->f_transform);
+ pixman_f_transform_init_identity (&crtc->f_inverse);
+
+ if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
+ return NULL;
+
+ /* attach the screen and crtc together */
+ crtc->pScreen = pScreen;
+ pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
+
+ return crtc;
+}
+
+/*
+ * Set the allowed rotations on a CRTC
+ */
+void
+RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
+{
+ crtc->rotations = rotations;
+}
+
+/*
+ * Set whether transforms are allowed on a CRTC
+ */
+void
+RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms)
+{
+ crtc->transforms = transforms;
+}
+
+/*
+ * Notify the extension that the Crtc has been reconfigured,
+ * the driver calls this whenever it has updated the mode
+ */
+Bool
+RRCrtcNotify (RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ RRTransformPtr transform,
+ int numOutputs,
+ RROutputPtr *outputs)
+{
+ int i, j;
+
+ /*
+ * Check to see if any of the new outputs were
+ * not in the old list and mark them as changed
+ */
+ for (i = 0; i < numOutputs; i++)
+ {
+ for (j = 0; j < crtc->numOutputs; j++)
+ if (outputs[i] == crtc->outputs[j])
+ break;
+ if (j == crtc->numOutputs)
+ {
+ outputs[i]->crtc = crtc;
+ RROutputChanged (outputs[i], FALSE);
+ RRCrtcChanged (crtc, FALSE);
+ }
+ }
+ /*
+ * Check to see if any of the old outputs are
+ * not in the new list and mark them as changed
+ */
+ for (j = 0; j < crtc->numOutputs; j++)
+ {
+ for (i = 0; i < numOutputs; i++)
+ if (outputs[i] == crtc->outputs[j])
+ break;
+ if (i == numOutputs)
+ {
+ if (crtc->outputs[j]->crtc == crtc)
+ crtc->outputs[j]->crtc = NULL;
+ RROutputChanged (crtc->outputs[j], FALSE);
+ RRCrtcChanged (crtc, FALSE);
+ }
+ }
+ /*
+ * Reallocate the crtc output array if necessary
+ */
+ if (numOutputs != crtc->numOutputs)
+ {
+ RROutputPtr *newoutputs;
+
+ if (numOutputs)
+ {
+ if (crtc->numOutputs)
+ newoutputs = realloc(crtc->outputs,
+ numOutputs * sizeof (RROutputPtr));
+ else
+ newoutputs = malloc(numOutputs * sizeof (RROutputPtr));
+ if (!newoutputs)
+ return FALSE;
+ }
+ else
+ {
+ free(crtc->outputs);
+ newoutputs = NULL;
+ }
+ crtc->outputs = newoutputs;
+ crtc->numOutputs = numOutputs;
+ }
+ /*
+ * Copy the new list of outputs into the crtc
+ */
+ memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr));
+ /*
+ * Update remaining crtc fields
+ */
+ if (mode != crtc->mode)
+ {
+ if (crtc->mode)
+ RRModeDestroy (crtc->mode);
+ crtc->mode = mode;
+ if (mode != NULL)
+ mode->refcnt++;
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (x != crtc->x)
+ {
+ crtc->x = x;
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (y != crtc->y)
+ {
+ crtc->y = y;
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (rotation != crtc->rotation)
+ {
+ crtc->rotation = rotation;
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (!RRTransformEqual (transform, &crtc->client_current_transform)) {
+ RRTransformCopy (&crtc->client_current_transform, transform);
+ RRCrtcChanged (crtc, TRUE);
+ }
+ if (crtc->changed && mode)
+ {
+ RRTransformCompute (x, y,
+ mode->mode.width, mode->mode.height,
+ rotation,
+ &crtc->client_current_transform,
+ &crtc->transform, &crtc->f_transform,
+ &crtc->f_inverse);
+ }
+ return TRUE;
+}
+
+void
+RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rrScrPriv (pScreen);
+ xRRCrtcChangeNotifyEvent ce;
+ RRModePtr mode = crtc->mode;
+
+ ce.type = RRNotify + RREventBase;
+ ce.subCode = RRNotify_CrtcChange;
+ ce.timestamp = pScrPriv->lastSetTime.milliseconds;
+ ce.window = pWin->drawable.id;
+ ce.crtc = crtc->id;
+ ce.rotation = crtc->rotation;
+ if (mode)
+ {
+ ce.mode = mode->mode.id;
+ ce.x = crtc->x;
+ ce.y = crtc->y;
+ ce.width = mode->mode.width;
+ ce.height = mode->mode.height;
+ }
+ else
+ {
+ ce.mode = None;
+ ce.x = 0;
+ ce.y = 0;
+ ce.width = 0;
+ ce.height = 0;
+ }
+ WriteEventsToClient (client, 1, (xEvent *) &ce);
+}
+
+static Bool
+RRCrtcPendingProperties (RRCrtcPtr crtc)
+{
+ ScreenPtr pScreen = crtc->pScreen;
+ rrScrPriv(pScreen);
+ int o;
+
+ for (o = 0; o < pScrPriv->numOutputs; o++)
+ {
+ RROutputPtr output = pScrPriv->outputs[o];
+ if (output->crtc == crtc && output->pendingProperties)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom)
+{
+ *left = crtc->x;
+ *top = crtc->y;
+
+ switch (crtc->rotation) {
+ case RR_Rotate_0:
+ case RR_Rotate_180:
+ default:
+ *right = crtc->x + crtc->mode->mode.width;
+ *bottom = crtc->y + crtc->mode->mode.height;
+ return;
+ case RR_Rotate_90:
+ case RR_Rotate_270:
+ *right = crtc->x + crtc->mode->mode.height;
+ *bottom = crtc->y + crtc->mode->mode.width;
+ return;
+ }
+}
+
+/* overlapping counts as adjacent */
+static Bool
+crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b)
+{
+ /* left, right, top, bottom... */
+ int al, ar, at, ab;
+ int bl, br, bt, bb;
+ int cl, cr, ct, cb; /* the overlap, if any */
+
+ crtc_bounds(a, &al, &ar, &at, &ab);
+ crtc_bounds(b, &bl, &br, &bt, &bb);
+
+ cl = max(al, bl);
+ cr = min(ar, br);
+ ct = max(at, bt);
+ cb = min(ab, bb);
+
+ return (cl <= cr) && (ct <= cb);
+}
+
+/* Depth-first search and mark all CRTCs reachable from cur */
+static void
+mark_crtcs (rrScrPrivPtr pScrPriv, int *reachable, int cur)
+{
+ int i;
+ reachable[cur] = TRUE;
+ for (i = 0; i < pScrPriv->numCrtcs; ++i) {
+ if (reachable[i] || !pScrPriv->crtcs[i]->mode)
+ continue;
+ if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i]))
+ mark_crtcs(pScrPriv, reachable, i);
+ }
+}
+
+static void
+RRComputeContiguity (ScreenPtr pScreen)
+{
+ rrScrPriv(pScreen);
+ Bool discontiguous = TRUE;
+ int i, n = pScrPriv->numCrtcs;
+
+ int *reachable = calloc(n, sizeof(int));
+ if (!reachable)
+ goto out;
+
+ /* Find first enabled CRTC and start search for reachable CRTCs from it */
+ for (i = 0; i < n; ++i) {
+ if (pScrPriv->crtcs[i]->mode) {
+ mark_crtcs(pScrPriv, reachable, i);
+ break;
+ }
+ }
+
+ /* Check that all enabled CRTCs were marked as reachable */
+ for (i = 0; i < n; ++i)
+ if (pScrPriv->crtcs[i]->mode && !reachable[i])
+ goto out;
+
+ discontiguous = FALSE;
+
+out:
+ free(reachable);
+ pScrPriv->discontiguous = discontiguous;
+}
+
+/*
+ * Request that the Crtc be reconfigured
+ */
+Bool
+RRCrtcSet (RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int numOutputs,
+ RROutputPtr *outputs)
+{
+ ScreenPtr pScreen = crtc->pScreen;
+ Bool ret = FALSE;
+ Bool recompute = TRUE;
+ rrScrPriv(pScreen);
+
+ /* See if nothing changed */
+ if (crtc->mode == mode &&
+ crtc->x == x &&
+ crtc->y == y &&
+ crtc->rotation == rotation &&
+ crtc->numOutputs == numOutputs &&
+ !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
+ !RRCrtcPendingProperties (crtc) &&
+ !RRCrtcPendingTransform (crtc))
+ {
+ recompute = FALSE;
+ ret = TRUE;
+ }
+ else
+ {
+#if RANDR_12_INTERFACE
+ if (pScrPriv->rrCrtcSet)
+ {
+ ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
+ rotation, numOutputs, outputs);
+ }
+ else
+#endif
+ {
+#if RANDR_10_INTERFACE
+ if (pScrPriv->rrSetConfig)
+ {
+ RRScreenSize size;
+ RRScreenRate rate;
+
+ if (!mode)
+ {
+ RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL);
+ ret = TRUE;
+ }
+ else
+ {
+ size.width = mode->mode.width;
+ size.height = mode->mode.height;
+ if (outputs[0]->mmWidth && outputs[0]->mmHeight)
+ {
+ size.mmWidth = outputs[0]->mmWidth;
+ size.mmHeight = outputs[0]->mmHeight;
+ }
+ else
+ {
+ size.mmWidth = pScreen->mmWidth;
+ size.mmHeight = pScreen->mmHeight;
+ }
+ size.nRates = 1;
+ rate.rate = RRVerticalRefresh (&mode->mode);
+ size.pRates = &rate;
+ ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
+ /*
+ * Old 1.0 interface tied screen size to mode size
+ */
+ if (ret)
+ {
+ RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs);
+ RRScreenSizeNotify (pScreen);
+ }
+ }
+ }
+#endif
+ }
+ if (ret)
+ {
+ int o;
+ RRTellChanged (pScreen);
+
+ for (o = 0; o < numOutputs; o++)
+ RRPostPendingProperties (outputs[o]);
+ }
+ }
+
+ if (recompute)
+ RRComputeContiguity(pScreen);
+
+ return ret;
+}
+
+/*
+ * Return crtc transform
+ */
+RRTransformPtr
+RRCrtcGetTransform (RRCrtcPtr crtc)
+{
+ RRTransformPtr transform = &crtc->client_pending_transform;
+
+ if (pixman_transform_is_identity (&transform->transform))
+ return NULL;
+ return transform;
+}
+
+/*
+ * Check whether the pending and current transforms are the same
+ */
+Bool
+RRCrtcPendingTransform (RRCrtcPtr crtc)
+{
+ return memcmp (&crtc->client_current_transform.transform,
+ &crtc->client_pending_transform.transform,
+ sizeof (PictTransform)) != 0;
+}
+
+/*
+ * Destroy a Crtc at shutdown
+ */
+void
+RRCrtcDestroy (RRCrtcPtr crtc)
+{
+ FreeResource (crtc->id, 0);
+}
+
+static int
+RRCrtcDestroyResource (pointer value, XID pid)
+{
+ RRCrtcPtr crtc = (RRCrtcPtr) value;
+ ScreenPtr pScreen = crtc->pScreen;
+
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+ int i;
+
+ for (i = 0; i < pScrPriv->numCrtcs; i++)
+ {
+ if (pScrPriv->crtcs[i] == crtc)
+ {
+ memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
+ (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr));
+ --pScrPriv->numCrtcs;
+ break;
+ }
+ }
+ }
+ free(crtc->gammaRed);
+ if (crtc->mode)
+ RRModeDestroy (crtc->mode);
+ free(crtc);
+ return 1;
+}
+
+/*
+ * Request that the Crtc gamma be changed
+ */
+
+Bool
+RRCrtcGammaSet (RRCrtcPtr crtc,
+ CARD16 *red,
+ CARD16 *green,
+ CARD16 *blue)
+{
+ Bool ret = TRUE;
+#if RANDR_12_INTERFACE
+ ScreenPtr pScreen = crtc->pScreen;
+#endif
+
+ memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16));
+ memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16));
+ memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16));
+#if RANDR_12_INTERFACE
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+ if (pScrPriv->rrCrtcSetGamma)
+ ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
+ }
+#endif
+ return ret;
+}
+
+/*
+ * Request current gamma back from the DDX (if possible).
+ * This includes gamma size.
+ */
+Bool
+RRCrtcGammaGet(RRCrtcPtr crtc)
+{
+ Bool ret = TRUE;
+#if RANDR_12_INTERFACE
+ ScreenPtr pScreen = crtc->pScreen;
+#endif
+
+#if RANDR_12_INTERFACE
+ if (pScreen)
+ {
+ rrScrPriv(pScreen);
+ if (pScrPriv->rrCrtcGetGamma)
+ ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc);
+ }
+#endif
+ return ret;
+}
+
+/*
+ * Notify the extension that the Crtc gamma has been changed
+ * The driver calls this whenever it has changed the gamma values
+ * in the RRCrtcRec
+ */
+
+Bool
+RRCrtcGammaNotify (RRCrtcPtr crtc)
+{
+ return TRUE; /* not much going on here */
+}
+
+static void
+RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
+ int *width, int *height)
+{
+ BoxRec box;
+
+ if (mode == NULL) {
+ *width = 0;
+ *height = 0;
+ return;
+ }
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = mode->mode.width;
+ box.y2 = mode->mode.height;
+
+ pixman_transform_bounds (transform, &box);
+ *width = box.x2 - box.x1;
+ *height = box.y2 - box.y1;
+}
+
+/**
+ * Returns the width/height that the crtc scans out from the framebuffer
+ */
+void
+RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
+{
+ RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height);
+}
+
+/*
+ * Set the size of the gamma table at server startup time
+ */
+
+Bool
+RRCrtcGammaSetSize (RRCrtcPtr crtc,
+ int size)
+{
+ CARD16 *gamma;
+
+ if (size == crtc->gammaSize)
+ return TRUE;
+ if (size)
+ {
+ gamma = malloc(size * 3 * sizeof (CARD16));
+ if (!gamma)
+ return FALSE;
+ }
+ else
+ gamma = NULL;
+ free(crtc->gammaRed);
+ crtc->gammaRed = gamma;
+ crtc->gammaGreen = gamma + size;
+ crtc->gammaBlue = gamma + size*2;
+ crtc->gammaSize = size;
+ return TRUE;
+}
+
+/*
+ * Set the pending CRTC transformation
+ */
+
+int
+RRCrtcTransformSet (RRCrtcPtr crtc,
+ PictTransformPtr transform,
+ struct pixman_f_transform *f_transform,
+ struct pixman_f_transform *f_inverse,
+ char *filter_name,
+ int filter_len,
+ xFixed *params,
+ int nparams)
+{
+ PictFilterPtr filter = NULL;
+ int width = 0, height = 0;
+
+ if (!crtc->transforms)
+ return BadValue;
+
+ if (filter_len)
+ {
+ filter = PictureFindFilter (crtc->pScreen,
+ filter_name,
+ filter_len);
+ if (!filter)
+ return BadName;
+ if (filter->ValidateParams)
+ {
+ if (!filter->ValidateParams (crtc->pScreen, filter->id,
+ params, nparams, &width, &height))
+ return BadMatch;
+ }
+ else {
+ width = filter->width;
+ height = filter->height;
+ }
+ }
+ else
+ {
+ if (nparams)
+ return BadMatch;
+ }
+ if (!RRTransformSetFilter (&crtc->client_pending_transform,
+ filter, params, nparams, width, height))
+ return BadAlloc;
+
+ crtc->client_pending_transform.transform = *transform;
+ crtc->client_pending_transform.f_transform = *f_transform;
+ crtc->client_pending_transform.f_inverse = *f_inverse;
+ return Success;
+}
+
+/*
+ * Initialize crtc type
+ */
+Bool
+RRCrtcInit (void)
+{
+ RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC");
+ if (!RRCrtcType)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * Initialize crtc type error value
+ */
+void
+RRCrtcInitErrorValue(void)
+{
+ SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc);
+}
+
+int
+ProcRRGetCrtcInfo (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcInfoReq);
+ xRRGetCrtcInfoReply rep;
+ RRCrtcPtr crtc;
+ CARD8 *extra;
+ unsigned long extraLen;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ RRModePtr mode;
+ RROutput *outputs;
+ RROutput *possible;
+ int i, j, k, n;
+ int width, height;
+ BoxRec panned_area;
+
+ REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* All crtcs must be associated with screens before client
+ * requests are processed
+ */
+ pScreen = crtc->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ mode = crtc->mode;
+
+ rep.type = X_Reply;
+ rep.status = RRSetConfigSuccess;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+ if (pScrPriv->rrGetPanning &&
+ pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) &&
+ (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1))
+ {
+ rep.x = panned_area.x1;
+ rep.y = panned_area.y1;
+ rep.width = panned_area.x2 - panned_area.x1;
+ rep.height = panned_area.y2 - panned_area.y1;
+ }
+ else
+ {
+ RRCrtcGetScanoutSize (crtc, &width, &height);
+ rep.x = crtc->x;
+ rep.y = crtc->y;
+ rep.width = width;
+ rep.height = height;
+ }
+ rep.mode = mode ? mode->mode.id : 0;
+ rep.rotation = crtc->rotation;
+ rep.rotations = crtc->rotations;
+ rep.nOutput = crtc->numOutputs;
+ k = 0;
+ for (i = 0; i < pScrPriv->numOutputs; i++)
+ for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
+ if (pScrPriv->outputs[i]->crtcs[j] == crtc)
+ k++;
+ rep.nPossibleOutput = k;
+
+ rep.length = rep.nOutput + rep.nPossibleOutput;
+
+ extraLen = rep.length << 2;
+ if (extraLen)
+ {
+ extra = malloc(extraLen);
+ if (!extra)
+ return BadAlloc;
+ }
+ else
+ extra = NULL;
+
+ outputs = (RROutput *) extra;
+ possible = (RROutput *) (outputs + rep.nOutput);
+
+ for (i = 0; i < crtc->numOutputs; i++)
+ {
+ outputs[i] = crtc->outputs[i]->id;
+ if (client->swapped)
+ swapl (&outputs[i], n);
+ }
+ k = 0;
+ for (i = 0; i < pScrPriv->numOutputs; i++)
+ for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
+ if (pScrPriv->outputs[i]->crtcs[j] == crtc)
+ {
+ possible[k] = pScrPriv->outputs[i]->id;
+ if (client->swapped)
+ swapl (&possible[k], n);
+ k++;
+ }
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.timestamp, n);
+ swaps(&rep.x, n);
+ swaps(&rep.y, n);
+ swaps(&rep.width, n);
+ swaps(&rep.height, n);
+ swapl(&rep.mode, n);
+ swaps(&rep.rotation, n);
+ swaps(&rep.rotations, n);
+ swaps(&rep.nOutput, n);
+ swaps(&rep.nPossibleOutput, n);
+ }
+ WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep);
+ if (extraLen)
+ {
+ WriteToClient (client, extraLen, (char *) extra);
+ free(extra);
+ }
+
+ return Success;
+}
+
+int
+ProcRRSetCrtcConfig (ClientPtr client)
+{
+ REQUEST(xRRSetCrtcConfigReq);
+ xRRSetCrtcConfigReply rep;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ RRCrtcPtr crtc;
+ RRModePtr mode;
+ int numOutputs;
+ RROutputPtr *outputs = NULL;
+ RROutput *outputIds;
+ TimeStamp configTime;
+ TimeStamp time;
+ Rotation rotation;
+ int rc, i, j;
+
+ REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
+ numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq)));
+
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess);
+
+ if (stuff->mode == None)
+ {
+ mode = NULL;
+ if (numOutputs > 0)
+ return BadMatch;
+ }
+ else
+ {
+ VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess);
+ if (numOutputs == 0)
+ return BadMatch;
+ }
+ if (numOutputs)
+ {
+ outputs = malloc(numOutputs * sizeof (RROutputPtr));
+ if (!outputs)
+ return BadAlloc;
+ }
+ else
+ outputs = NULL;
+
+ outputIds = (RROutput *) (stuff + 1);
+ for (i = 0; i < numOutputs; i++)
+ {
+ rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i],
+ RROutputType, client, DixSetAttrAccess);
+ if (rc != Success)
+ {
+ free(outputs);
+ return rc;
+ }
+ /* validate crtc for this output */
+ for (j = 0; j < outputs[i]->numCrtcs; j++)
+ if (outputs[i]->crtcs[j] == crtc)
+ break;
+ if (j == outputs[i]->numCrtcs)
+ {
+ free(outputs);
+ return BadMatch;
+ }
+ /* validate mode for this output */
+ for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
+ {
+ RRModePtr m = (j < outputs[i]->numModes ?
+ outputs[i]->modes[j] :
+ outputs[i]->userModes[j - outputs[i]->numModes]);
+ if (m == mode)
+ break;
+ }
+ if (j == outputs[i]->numModes + outputs[i]->numUserModes)
+ {
+ free(outputs);
+ return BadMatch;
+ }
+ }
+ /* validate clones */
+ for (i = 0; i < numOutputs; i++)
+ {
+ for (j = 0; j < numOutputs; j++)
+ {
+ int k;
+ if (i == j)
+ continue;
+ for (k = 0; k < outputs[i]->numClones; k++)
+ {
+ if (outputs[i]->clones[k] == outputs[j])
+ break;
+ }
+ if (k == outputs[i]->numClones)
+ {
+ free(outputs);
+ return BadMatch;
+ }
+ }
+ }
+
+ pScreen = crtc->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ time = ClientTimeToServerTime(stuff->timestamp);
+ configTime = ClientTimeToServerTime(stuff->configTimestamp);
+
+ if (!pScrPriv)
+ {
+ time = currentTime;
+ rep.status = RRSetConfigFailed;
+ goto sendReply;
+ }
+
+ /*
+ * Validate requested rotation
+ */
+ rotation = (Rotation) stuff->rotation;
+
+ /* test the rotation bits only! */
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ case RR_Rotate_90:
+ case RR_Rotate_180:
+ case RR_Rotate_270:
+ break;
+ default:
+ /*
+ * Invalid rotation
+ */
+ client->errorValue = stuff->rotation;
+ free(outputs);
+ return BadValue;
+ }
+
+ if (mode)
+ {
+ if ((~crtc->rotations) & rotation)
+ {
+ /*
+ * requested rotation or reflection not supported by screen
+ */
+ client->errorValue = stuff->rotation;
+ free(outputs);
+ return BadMatch;
+ }
+
+#ifdef RANDR_12_INTERFACE
+ /*
+ * Check screen size bounds if the DDX provides a 1.2 interface
+ * for setting screen size. Else, assume the CrtcSet sets
+ * the size along with the mode. If the driver supports transforms,
+ * then it must allow crtcs to display a subset of the screen, so
+ * only do this check for drivers without transform support.
+ */
+ if (pScrPriv->rrScreenSetSize && !crtc->transforms)
+ {
+ int source_width;
+ int source_height;
+ PictTransform transform;
+ struct pixman_f_transform f_transform, f_inverse;
+
+ RRTransformCompute (stuff->x, stuff->y,
+ mode->mode.width, mode->mode.height,
+ rotation,
+ &crtc->client_pending_transform,
+ &transform, &f_transform, &f_inverse);
+
+ RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
+ if (stuff->x + source_width > pScreen->width)
+ {
+ client->errorValue = stuff->x;
+ free(outputs);
+ return BadValue;
+ }
+
+ if (stuff->y + source_height > pScreen->height)
+ {
+ client->errorValue = stuff->y;
+ free(outputs);
+ return BadValue;
+ }
+ }
+#endif
+ }
+
+ if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
+ rotation, numOutputs, outputs))
+ {
+ rep.status = RRSetConfigFailed;
+ goto sendReply;
+ }
+ rep.status = RRSetConfigSuccess;
+ pScrPriv->lastSetTime = time;
+
+sendReply:
+ free(outputs);
+
+ rep.type = X_Reply;
+ /* rep.status has already been filled in */
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
+
+ if (client->swapped)
+ {
+ int n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.newTimestamp, n);
+ }
+ WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep);
+
+ return Success;
+}
+
+int
+ProcRRGetPanning (ClientPtr client)
+{
+ REQUEST(xRRGetPanningReq);
+ xRRGetPanningReply rep;
+ RRCrtcPtr crtc;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ BoxRec total;
+ BoxRec tracking;
+ INT16 border[4];
+ int n;
+
+ REQUEST_SIZE_MATCH(xRRGetPanningReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* All crtcs must be associated with screens before client
+ * requests are processed
+ */
+ pScreen = crtc->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ if (!pScrPriv)
+ return RRErrorBase + BadRRCrtc;
+
+ memset(&rep, 0, sizeof(rep));
+ rep.type = X_Reply;
+ rep.status = RRSetConfigSuccess;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 1;
+ rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+
+ if (pScrPriv->rrGetPanning &&
+ pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) {
+ rep.left = total.x1;
+ rep.top = total.y1;
+ rep.width = total.x2 - total.x1;
+ rep.height = total.y2 - total.y1;
+ rep.track_left = tracking.x1;
+ rep.track_top = tracking.y1;
+ rep.track_width = tracking.x2 - tracking.x1;
+ rep.track_height = tracking.y2 - tracking.y1;
+ rep.border_left = border[0];
+ rep.border_top = border[1];
+ rep.border_right = border[2];
+ rep.border_bottom = border[3];
+ }
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.timestamp, n);
+ swaps(&rep.left, n);
+ swaps(&rep.top, n);
+ swaps(&rep.width, n);
+ swaps(&rep.height, n);
+ swaps(&rep.track_left, n);
+ swaps(&rep.track_top, n);
+ swaps(&rep.track_width, n);
+ swaps(&rep.track_height, n);
+ swaps(&rep.border_left, n);
+ swaps(&rep.border_top, n);
+ swaps(&rep.border_right, n);
+ swaps(&rep.border_bottom, n);
+ }
+ WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep);
+ return Success;
+}
+
+int
+ProcRRSetPanning (ClientPtr client)
+{
+ REQUEST(xRRSetPanningReq);
+ xRRSetPanningReply rep;
+ RRCrtcPtr crtc;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ TimeStamp time;
+ BoxRec total;
+ BoxRec tracking;
+ INT16 border[4];
+ int n;
+
+ REQUEST_SIZE_MATCH(xRRSetPanningReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* All crtcs must be associated with screens before client
+ * requests are processed
+ */
+ pScreen = crtc->pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ if (!pScrPriv) {
+ time = currentTime;
+ rep.status = RRSetConfigFailed;
+ goto sendReply;
+ }
+
+ time = ClientTimeToServerTime(stuff->timestamp);
+
+ if (!pScrPriv->rrGetPanning)
+ return RRErrorBase + BadRRCrtc;
+
+ total.x1 = stuff->left;
+ total.y1 = stuff->top;
+ total.x2 = total.x1 + stuff->width;
+ total.y2 = total.y1 + stuff->height;
+ tracking.x1 = stuff->track_left;
+ tracking.y1 = stuff->track_top;
+ tracking.x2 = tracking.x1 + stuff->track_width;
+ tracking.y2 = tracking.y1 + stuff->track_height;
+ border[0] = stuff->border_left;
+ border[1] = stuff->border_top;
+ border[2] = stuff->border_right;
+ border[3] = stuff->border_bottom;
+
+ if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border))
+ return BadMatch;
+
+ pScrPriv->lastSetTime = time;
+
+ rep.status = RRSetConfigSuccess;
+
+sendReply:
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.newTimestamp, n);
+ }
+ WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep);
+ return Success;
+}
+
+int
+ProcRRGetCrtcGammaSize (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcGammaSizeReq);
+ xRRGetCrtcGammaSizeReply reply;
+ RRCrtcPtr crtc;
+ int n;
+
+ REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* Gamma retrieval failed, any better error? */
+ if (!RRCrtcGammaGet(crtc))
+ return RRErrorBase + BadRRCrtc;
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = 0;
+ reply.size = crtc->gammaSize;
+ if (client->swapped) {
+ swaps (&reply.sequenceNumber, n);
+ swapl (&reply.length, n);
+ swaps (&reply.size, n);
+ }
+ WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply);
+ return Success;
+}
+
+int
+ProcRRGetCrtcGamma (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcGammaReq);
+ xRRGetCrtcGammaReply reply;
+ RRCrtcPtr crtc;
+ int n;
+ unsigned long len;
+ char *extra = NULL;
+
+ REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ /* Gamma retrieval failed, any better error? */
+ if (!RRCrtcGammaGet(crtc))
+ return RRErrorBase + BadRRCrtc;
+
+ len = crtc->gammaSize * 3 * 2;
+
+ if (crtc->gammaSize) {
+ extra = malloc(len);
+ if (!extra)
+ return BadAlloc;
+ }
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = bytes_to_int32(len);
+ reply.size = crtc->gammaSize;
+ if (client->swapped) {
+ swaps (&reply.sequenceNumber, n);
+ swapl (&reply.length, n);
+ swaps (&reply.size, n);
+ }
+ WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply);
+ if (crtc->gammaSize)
+ {
+ memcpy(extra, crtc->gammaRed, len);
+ client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write;
+ WriteSwappedDataToClient (client, len, extra);
+ free(extra);
+ }
+ return Success;
+}
+
+int
+ProcRRSetCrtcGamma (ClientPtr client)
+{
+ REQUEST(xRRSetCrtcGammaReq);
+ RRCrtcPtr crtc;
+ unsigned long len;
+ CARD16 *red, *green, *blue;
+
+ REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq));
+ if (len < (stuff->size * 3 + 1) >> 1)
+ return BadLength;
+
+ if (stuff->size != crtc->gammaSize)
+ return BadMatch;
+
+ red = (CARD16 *) (stuff + 1);
+ green = red + crtc->gammaSize;
+ blue = green + crtc->gammaSize;
+
+ RRCrtcGammaSet (crtc, red, green, blue);
+
+ return Success;
+}
+
+/* Version 1.3 additions */
+
+int
+ProcRRSetCrtcTransform (ClientPtr client)
+{
+ REQUEST(xRRSetCrtcTransformReq);
+ RRCrtcPtr crtc;
+ PictTransform transform;
+ struct pixman_f_transform f_transform, f_inverse;
+ char *filter;
+ int nbytes;
+ xFixed *params;
+ int nparams;
+
+ REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ PictTransform_from_xRenderTransform (&transform, &stuff->transform);
+ pixman_f_transform_from_pixman_transform (&f_transform, &transform);
+ if (!pixman_f_transform_invert (&f_inverse, &f_transform))
+ return BadMatch;
+
+ filter = (char *) (stuff + 1);
+ nbytes = stuff->nbytesFilter;
+ params = (xFixed *) (filter + pad_to_int32(nbytes));
+ nparams = ((xFixed *) stuff + client->req_len) - params;
+ if (nparams < 0)
+ return BadLength;
+
+ return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse,
+ filter, nbytes, params, nparams);
+}
+
+
+#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32)
+
+static int
+transform_filter_length (RRTransformPtr transform)
+{
+ int nbytes, nparams;
+
+ if (transform->filter == NULL)
+ return 0;
+ nbytes = strlen (transform->filter->name);
+ nparams = transform->nparams;
+ return pad_to_int32(nbytes) + (nparams * sizeof (xFixed));
+}
+
+static int
+transform_filter_encode (ClientPtr client, char *output,
+ CARD16 *nbytesFilter,
+ CARD16 *nparamsFilter,
+ RRTransformPtr transform)
+{
+ int nbytes, nparams;
+ int n;
+
+ if (transform->filter == NULL) {
+ *nbytesFilter = 0;
+ *nparamsFilter = 0;
+ return 0;
+ }
+ nbytes = strlen (transform->filter->name);
+ nparams = transform->nparams;
+ *nbytesFilter = nbytes;
+ *nparamsFilter = nparams;
+ memcpy (output, transform->filter->name, nbytes);
+ while ((nbytes & 3) != 0)
+ output[nbytes++] = 0;
+ memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed));
+ if (client->swapped) {
+ swaps (nbytesFilter, n);
+ swaps (nparamsFilter, n);
+ SwapLongs ((CARD32 *) (output + nbytes), nparams);
+ }
+ nbytes += nparams * sizeof (xFixed);
+ return nbytes;
+}
+
+static void
+transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict)
+{
+ xRenderTransform_from_PictTransform (wire, pict);
+ if (client->swapped)
+ SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform)));
+}
+
+int
+ProcRRGetCrtcTransform (ClientPtr client)
+{
+ REQUEST(xRRGetCrtcTransformReq);
+ xRRGetCrtcTransformReply *reply;
+ RRCrtcPtr crtc;
+ int n, nextra;
+ RRTransformPtr current, pending;
+ char *extra;
+
+ REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq);
+ VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+ pending = &crtc->client_pending_transform;
+ current = &crtc->client_current_transform;
+
+ nextra = (transform_filter_length (pending) +
+ transform_filter_length (current));
+
+ reply = malloc(sizeof (xRRGetCrtcTransformReply) + nextra);
+ if (!reply)
+ return BadAlloc;
+
+ extra = (char *) (reply + 1);
+ reply->type = X_Reply;
+ reply->sequenceNumber = client->sequence;
+ reply->length = bytes_to_int32(CrtcTransformExtra + nextra);
+
+ reply->hasTransforms = crtc->transforms;
+
+ transform_encode (client, &reply->pendingTransform, &pending->transform);
+ extra += transform_filter_encode (client, extra,
+ &reply->pendingNbytesFilter,
+ &reply->pendingNparamsFilter,
+ pending);
+
+ transform_encode (client, &reply->currentTransform, &current->transform);
+ extra += transform_filter_encode (client, extra,
+ &reply->currentNbytesFilter,
+ &reply->currentNparamsFilter,
+ current);
+
+ if (client->swapped) {
+ swaps (&reply->sequenceNumber, n);
+ swapl (&reply->length, n);
+ }
+ WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply);
+ free(reply);
+ return Success;
+}
+
+void
+RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, int *y)
+{
+ rrScrPriv (pScreen);
+ int i;
+
+ /* intentional dead space -> let it float */
+ if (pScrPriv->discontiguous)
+ return;
+
+ /* if we're moving inside a crtc, we're fine */
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+
+ int left, right, top, bottom;
+
+ if (!crtc->mode)
+ continue;
+
+ crtc_bounds(crtc, &left, &right, &top, &bottom);
+
+ if ((*x >= left) && (*x <= right) && (*y >= top) && (*y <= bottom))
+ return;
+ }
+
+ /* if we're trying to escape, clamp to the CRTC we're coming from */
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+ int nx, ny;
+ int left, right, top, bottom;
+
+ if (!crtc->mode)
+ continue;
+
+ crtc_bounds(crtc, &left, &right, &top, &bottom);
+ miPointerGetPosition(pDev, &nx, &ny);
+
+ if ((nx >= left) && (nx <= right) && (ny >= top) && (ny <= bottom)) {
+ if ((*x <= left) || (*x >= right)) {
+ int dx = *x - nx;
+
+ if (dx > 0)
+ *x = right;
+ else if (dx < 0)
+ *x = left;
+ }
+
+ if ((*y <= top) || (*y >= bottom)) {
+ int dy = *y - ny;
+
+ if (dy > 0)
+ *y = bottom;
+ else if (dy < 0)
+ *y = top;
+ }
+
+ return;
+ }
+ }
+}