From dfc4a902af321f289f2942904bf201f76d0320d7 Mon Sep 17 00:00:00 2001 From: Sehong Na Date: Thu, 14 Nov 2013 14:56:39 +0900 Subject: [PATCH] init tizen_2.2.1 --- .gitignore | 111 - .gitmodules | 21 - .mailmap | 16 - Makefile.target | 0 gl/lib/Linux/x86/pkgconfig/egl.pc | 10 - gl/lib/Linux/x86/pkgconfig/glesv1_cm.pc | 11 - gl/lib/Linux/x86/pkgconfig/glesv2.pc | 12 - gl/lib/Linux/x86/pkgconfig/osmesa.pc | 12 - gl/lib/Linux/x86_64/pkgconfig/egl.pc | 10 - gl/lib/Linux/x86_64/pkgconfig/glesv1_cm.pc | 11 - gl/lib/Linux/x86_64/pkgconfig/glesv2.pc | 12 - gl/lib/Linux/x86_64/pkgconfig/osmesa.pc | 12 - hw/vga.c | 2 +- package/build.macos-64 | 18 +- package/changelog | 398 ++- package/emulator-qemu-x86.install.ubuntu-32 | 42 +- package/emulator-qemu-x86.install.ubuntu-64 | 42 +- package/emulator-qemu-x86.remove.ubuntu-32 | 40 +- package/emulator-qemu-x86.remove.ubuntu-64 | 40 +- package/pkginfo.manifest | 10 +- qemu-sockets.c | 2 + tizen/distrib/initscript/tizen_kvm | 24 - tizen/distrib/libav/libavcodec/libavcodec.v | 9 - tizen/distrib/libav/libavcodec/version.h | 72 - tizen/distrib/libav/libavdevice/libavdevice.v | 4 - tizen/distrib/libav/libavfilter/libavfilter.v | 4 - tizen/distrib/libav/libavformat/libavformat.v | 7 - tizen/distrib/libav/libavformat/version.h | 78 - tizen/distrib/libav/libavutil/libavutil.v | 4 - tizen/distrib/libav/libpostproc/libpostproc.v | 4 - tizen/distrib/libav/libswscale/libswscale.v | 4 - tizen/emulator_configure.sh | 13 +- tizen/src/Makefile | 4 + tizen/src/Makefile.tizen | 9 +- tizen/src/Makefile.tizen.arm | 0 tizen/src/Makefile.tizen.i386 | 0 tizen/src/debug_ch.c | 75 +- tizen/src/emulator.c | 25 +- tizen/src/guest_server.c | 249 +- tizen/src/hw/gloffscreen.h | 33 +- tizen/src/hw/gloffscreen_agl.c | 529 ++-- tizen/src/hw/gloffscreen_common.c | 472 +-- tizen/src/hw/gloffscreen_glx.c | 505 +-- tizen/src/hw/gloffscreen_test.c | 138 +- tizen/src/hw/gloffscreen_test.h | 2 +- tizen/src/hw/gloffscreen_wgl.c | 1228 ++++---- tizen/src/hw/gloffscreen_xcomposite.c | 512 +-- tizen/src/hw/helper_opengl.c | 239 +- tizen/src/hw/helper_opengl.h | 28 + tizen/src/hw/maru_board.c | 7 +- tizen/src/hw/maru_brill_codec.c | 1837 +++++++++++ tizen/src/hw/maru_brill_codec.h | 158 + tizen/src/hw/maru_camera_linux_pci.c | 23 +- tizen/src/hw/maru_codec.c | 130 +- tizen/src/hw/maru_device_ids.h | 2 + tizen/src/hw/maru_virtio_hwkey.c | 72 +- tizen/src/hw/maru_virtio_touchscreen.c | 28 +- tizen/src/hw/opengl_exec.c | 2355 ++++++++------ tizen/src/hw/opengl_exec.h | 7 +- tizen/src/hw/opengl_func.h | 194 +- tizen/src/hw/opengl_process.h | 6 +- tizen/src/hw/parse_gl_h.c | 2759 ++++++++--------- tizen/src/hw/range_alloc.h | 4 - tizen/src/hw/virtio-gl-stub.c | 5 +- tizen/src/hw/virtio-gl.c | 259 +- tizen/src/maru_display.c | 28 +- tizen/src/maru_display.h | 10 +- tizen/src/maru_sdl.c | 619 ++-- tizen/src/maru_sdl.h | 11 +- tizen/src/maru_shm.c | 13 +- tizen/src/maru_shm.h | 5 +- tizen/src/mloop_event.c | 20 +- tizen/src/osutil-darwin.c | 56 +- tizen/src/osutil-linux.c | 43 +- tizen/src/osutil-win32.c | 38 +- tizen/src/osutil.h | 2 + tizen/src/skin/client/.project | 17 - .../default.dbi | 0 .../default_0.png | Bin .../default_0_p.png | Bin .../default_180.png | Bin .../default_180_p.png | Bin .../default_L90.png | Bin .../default_L90_p.png | Bin .../default_R90.png | Bin .../default_R90_p.png | Bin .../info.ini | 0 .../default.dbi | 0 .../default_0.png | Bin .../default_0_p.png | Bin .../default_180.png | Bin .../default_180_p.png | Bin .../default_L90.png | Bin .../default_L90_p.png | Bin .../default_R90.png | Bin .../default_R90_p.png | Bin .../info.ini.bak | 0 .../skins/emul-540x960-3btn/default.dbi | 245 ++ .../skins/emul-540x960-3btn/default_0.png | Bin 0 -> 56734 bytes .../skins/emul-540x960-3btn/default_0_p.png | Bin 0 -> 62762 bytes .../skins/emul-540x960-3btn/default_180.png | Bin 0 -> 57165 bytes .../skins/emul-540x960-3btn/default_180_p.png | Bin 0 -> 63582 bytes .../skins/emul-540x960-3btn/default_L90.png | Bin 0 -> 53190 bytes .../skins/emul-540x960-3btn/default_L90_p.png | Bin 0 -> 59676 bytes .../skins/emul-540x960-3btn/default_R90.png | Bin 0 -> 52643 bytes .../skins/emul-540x960-3btn/default_R90_p.png | Bin 0 -> 59677 bytes .../client/skins/emul-540x960-3btn/info.ini | 4 + .../default.dbi | 0 .../default_0.png | Bin .../default_0_p.png | Bin .../default_180.png | Bin .../default_180_p.png | Bin .../default_L90.png | Bin .../default_L90_p.png | Bin .../default_R90.png | Bin .../default_R90_p.png | Bin .../info.ini | 0 .../default.dbi | 0 .../default_0.png | Bin .../default_0_p.png | Bin .../default_180.png | Bin .../default_180_p.png | Bin .../default_L90.png | Bin .../default_L90_p.png | Bin .../default_R90.png | Bin .../default_R90_p.png | Bin .../info.ini.bak | 0 .../client/skins/emul-general/default.dbi | 55 - .../client/skins/emul-general/info.ini.bak | 4 - .../tizen/emulator/skin/EmulatorFingers.java | 6 +- .../tizen/emulator/skin/EmulatorSdlSkin.java | 13 +- .../tizen/emulator/skin/EmulatorShmSkin.java | 13 +- .../org/tizen/emulator/skin/EmulatorSkin.java | 208 +- .../tizen/emulator/skin/EmulatorSkinMain.java | 36 +- .../skin/comm/sock/SocketCommunicator.java | 3 +- .../emulator/skin/custom/CustomButton.java | 2 +- .../tizen/emulator/skin/custom/KeyWindow.java | 6 +- .../emulator/skin/dialog/AboutDialog.java | 2 - .../skin/dialog/DetailInfoDialog.java | 3 +- .../emulator/skin/dialog/SkinDialog.java | 4 +- .../layout/GeneralPurposeSkinComposer.java | 54 +- .../org/tizen/emulator/skin/layout/HWKey.java | 25 +- ....java => ProfileSpecificSkinComposer.java} | 138 +- .../emulator/skin/layout/SkinPatches.java | 6 +- .../skin/screenshot/ScreenShotDialog.java | 59 +- .../skin/screenshot/SdlScreenShotWindow.java | 2 +- .../tizen/emulator/skin/util/CocoaUtil.java | 106 + .../tizen/emulator/skin/util/SkinUtil.java | 20 +- tizen/src/skin/maruskin_operation.c | 98 +- tizen/src/skin/maruskin_operation.h | 1 + tizen/src/skin/maruskin_server.c | 8 +- 151 files changed, 9072 insertions(+), 5860 deletions(-) delete mode 100644 .gitignore delete mode 100644 .gitmodules delete mode 100644 .mailmap mode change 100755 => 100644 Makefile.target delete mode 100644 gl/lib/Linux/x86/pkgconfig/egl.pc delete mode 100644 gl/lib/Linux/x86/pkgconfig/glesv1_cm.pc delete mode 100644 gl/lib/Linux/x86/pkgconfig/glesv2.pc delete mode 100644 gl/lib/Linux/x86/pkgconfig/osmesa.pc delete mode 100644 gl/lib/Linux/x86_64/pkgconfig/egl.pc delete mode 100644 gl/lib/Linux/x86_64/pkgconfig/glesv1_cm.pc delete mode 100644 gl/lib/Linux/x86_64/pkgconfig/glesv2.pc delete mode 100644 gl/lib/Linux/x86_64/pkgconfig/osmesa.pc delete mode 100755 tizen/distrib/initscript/tizen_kvm delete mode 100644 tizen/distrib/libav/libavcodec/libavcodec.v delete mode 100644 tizen/distrib/libav/libavcodec/version.h delete mode 100644 tizen/distrib/libav/libavdevice/libavdevice.v delete mode 100644 tizen/distrib/libav/libavfilter/libavfilter.v delete mode 100644 tizen/distrib/libav/libavformat/libavformat.v delete mode 100644 tizen/distrib/libav/libavformat/version.h delete mode 100644 tizen/distrib/libav/libavutil/libavutil.v delete mode 100644 tizen/distrib/libav/libpostproc/libpostproc.v delete mode 100644 tizen/distrib/libav/libswscale/libswscale.v mode change 100755 => 100644 tizen/src/Makefile mode change 100755 => 100644 tizen/src/Makefile.tizen mode change 100755 => 100644 tizen/src/Makefile.tizen.arm mode change 100755 => 100644 tizen/src/Makefile.tizen.i386 create mode 100644 tizen/src/hw/helper_opengl.h create mode 100644 tizen/src/hw/maru_brill_codec.c create mode 100644 tizen/src/hw/maru_brill_codec.h delete mode 100644 tizen/src/skin/client/.project rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default.dbi (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default_0.png (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default_0_p.png (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default_180.png (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default_180_p.png (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default_L90.png (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default_L90_p.png (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default_R90.png (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/default_R90_p.png (100%) rename tizen/src/skin/client/skins/{emul-320x480 => emul-320x480-1btn}/info.ini (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default.dbi (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default_0.png (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default_0_p.png (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default_180.png (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default_180_p.png (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default_L90.png (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default_L90_p.png (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default_R90.png (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/default_R90_p.png (100%) rename tizen/src/skin/client/skins/{emul-480x800 => emul-480x800-1btn}/info.ini.bak (100%) create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default.dbi create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default_0.png create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default_0_p.png create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default_180.png create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default_180_p.png create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default_L90.png create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default_L90_p.png create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default_R90.png create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/default_R90_p.png create mode 100644 tizen/src/skin/client/skins/emul-540x960-3btn/info.ini rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default.dbi (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default_0.png (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default_0_p.png (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default_180.png (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default_180_p.png (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default_L90.png (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default_L90_p.png (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default_R90.png (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/default_R90_p.png (100%) rename tizen/src/skin/client/skins/{emul-600x1024 => emul-600x1024-1btn}/info.ini (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default.dbi (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default_0.png (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default_0_p.png (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default_180.png (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default_180_p.png (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default_L90.png (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default_L90_p.png (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default_R90.png (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/default_R90_p.png (100%) rename tizen/src/skin/client/skins/{emul-720x1280 => emul-720x1280-1btn}/info.ini.bak (100%) delete mode 100644 tizen/src/skin/client/skins/emul-general/default.dbi delete mode 100644 tizen/src/skin/client/skins/emul-general/info.ini.bak rename tizen/src/skin/client/src/org/tizen/emulator/skin/layout/{PhoneShapeSkinComposer.java => ProfileSpecificSkinComposer.java} (84%) create mode 100755 tizen/src/skin/client/src/org/tizen/emulator/skin/util/CocoaUtil.java diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 4070bb9943..0000000000 --- a/.gitignore +++ /dev/null @@ -1,111 +0,0 @@ -config-devices.* -config-all-devices.* -config-host.* -config-target.* -trace.h -trace.c -trace-dtrace.h -trace-dtrace.dtrace -*-timestamp -*-softmmu -*-darwin-user -*-linux-user -*-bsd-user -libdis* -libhw32 -libhw64 -libuser -linux-headers/asm -qapi-generated -qapi-types.[ch] -qapi-visit.[ch] -qmp-commands.h -qmp-marshal.c -qemu-doc.html -qemu-tech.html -qemu-doc.info -qemu-tech.info -qemu.1 -qemu.pod -qemu-img.1 -qemu-img.pod -qemu-img -qemu-nbd -qemu-nbd.8 -qemu-nbd.pod -qemu-options.def -qemu-options.texi -qemu-img-cmds.texi -qemu-img-cmds.h -qemu-io -qemu-ga -qemu-bridge-helper -qemu-monitor.texi -vscclient -QMP/qmp-commands.txt -test-coroutine -test-qmp-input-visitor -test-qmp-output-visitor -test-string-input-visitor -test-string-output-visitor -test-visitor-serialization -fsdev/virtfs-proxy-helper.1 -fsdev/virtfs-proxy-helper.pod -.gdbinit -*.a -*.aux -*.cp -*.dvi -*.exe -*.fn -*.ky -*.log -*.pdf -*.cps -*.fns -*.kys -*.pg -*.pyc -*.toc -*.tp -*.vr -*.d -*.o -*.lo -*.la -*.pc -.libs -*.swp -*.orig -.pc -patches -pc-bios/bios-pq/status -pc-bios/vgabios-pq/status -pc-bios/optionrom/linuxboot.bin -pc-bios/optionrom/linuxboot.raw -pc-bios/optionrom/linuxboot.img -pc-bios/optionrom/multiboot.bin -pc-bios/optionrom/multiboot.raw -pc-bios/optionrom/multiboot.img -pc-bios/optionrom/kvmvapic.bin -pc-bios/optionrom/kvmvapic.raw -pc-bios/optionrom/kvmvapic.img -.stgit-* -cscope.* -tags -TAGS -*~ -tizen/emulator -tizen/src/build_info.h -tizen/src/skin/client/src/about.properties -tizen/src/skin/client/bin -tizen/src/skin/client/build -tizen/src/skin/client/emulator-skin.jar -tizen/src/skin/client/lib -tizen/src/skin/client/native_src/*.so -tizen/src/skin/client/native_src/*.dynlib -tizen/src/check-cam -fsdev/virtfs-proxy-helper -.cproject -.project - diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index eca876f85d..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,21 +0,0 @@ -[submodule "roms/vgabios"] - path = roms/vgabios - url = git://git.qemu.org/vgabios.git/ -[submodule "roms/seabios"] - path = roms/seabios - url = git://git.qemu.org/seabios.git/ -[submodule "roms/SLOF"] - path = roms/SLOF - url = git://git.qemu.org/SLOF.git -[submodule "roms/ipxe"] - path = roms/ipxe - url = git://git.qemu.org/ipxe.git -[submodule "roms/openbios"] - path = roms/openbios - url = git://git.qemu.org/openbios.git -[submodule "roms/qemu-palcode"] - path = roms/qemu-palcode - url = git://repo.or.cz/qemu-palcode.git -[submodule "roms/sgabios"] - path = roms/sgabios - url = git://git.qemu.org/sgabios.git diff --git a/.mailmap b/.mailmap deleted file mode 100644 index 9797802aaa..0000000000 --- a/.mailmap +++ /dev/null @@ -1,16 +0,0 @@ -# This mailmap just translates the weird addresses from the original import into git -# into proper addresses so that they are counted properly in git shortlog output. -# -Andrzej Zaborowski balrog -Anthony Liguori aliguori -Aurelien Jarno aurel32 -Blue Swirl blueswir1 -Edgar E. Iglesias edgar_igl -Fabrice Bellard bellard -Jocelyn Mayer j_mayer -Paul Brook pbrook -Thiemo Seufer ths -malc malc -# There is also a: -# (no author) <(no author)@c046a42c-6fe2-441c-8c8c-71466251a162> -# for the cvs2svn initialization commit e63c3dc74bf. diff --git a/Makefile.target b/Makefile.target old mode 100755 new mode 100644 diff --git a/gl/lib/Linux/x86/pkgconfig/egl.pc b/gl/lib/Linux/x86/pkgconfig/egl.pc deleted file mode 100644 index e81e56c41f..0000000000 --- a/gl/lib/Linux/x86/pkgconfig/egl.pc +++ /dev/null @@ -1,10 +0,0 @@ -prefix=/home/stas/Projects/qemu/gl/dgles2/../lib/Linux/x86 -exec_prefix=${prefix} -libdir=${prefix}/lib -includedir=${prefix}/include - -Name: egl -Description: DGLES egl library -Version: 1.4.2 -Libs: -L${libdir} -lEGL -Cflags: -I${includedir} diff --git a/gl/lib/Linux/x86/pkgconfig/glesv1_cm.pc b/gl/lib/Linux/x86/pkgconfig/glesv1_cm.pc deleted file mode 100644 index c5c3508eaa..0000000000 --- a/gl/lib/Linux/x86/pkgconfig/glesv1_cm.pc +++ /dev/null @@ -1,11 +0,0 @@ -prefix=/home/stas/Projects/qemu/gl/dgles2/../lib/Linux/x86 -exec_prefix=${prefix} -libdir=${prefix}/lib -includedir=${prefix}/include - -Name: glesv1_cm -Description: DGLES OpenGL ES 1.1 CM library -Requires.private: egl -Version: 1.4.1 -Libs: -L${libdir} -lGLES_CM -Cflags: -I${includedir} diff --git a/gl/lib/Linux/x86/pkgconfig/glesv2.pc b/gl/lib/Linux/x86/pkgconfig/glesv2.pc deleted file mode 100644 index 1592feb9b1..0000000000 --- a/gl/lib/Linux/x86/pkgconfig/glesv2.pc +++ /dev/null @@ -1,12 +0,0 @@ -prefix=/home/stas/Projects/qemu/gl/dgles2/../lib/Linux/x86 -exec_prefix=${prefix} -libdir=${prefix}/lib -includedir=${prefix}/include - -Name: glesv2 -Description: DGLES OpenGL ES 2.0 library -Requires.private: egl -Version: 2.0.0 -Libs: -L${libdir} -lGLESv2 -Cflags: -I${includedir} - diff --git a/gl/lib/Linux/x86/pkgconfig/osmesa.pc b/gl/lib/Linux/x86/pkgconfig/osmesa.pc deleted file mode 100644 index 99a69f2181..0000000000 --- a/gl/lib/Linux/x86/pkgconfig/osmesa.pc +++ /dev/null @@ -1,12 +0,0 @@ -prefix=/home/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/mesa/../lib/Linux/x86 -exec_prefix=${prefix} -libdir=/home/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/mesa/../lib/Linux/x86 -includedir=/home/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/mesa/../include - -Name: osmesa -Description: Mesa Off-screen Rendering library -Requires: -Version: 8.0.3 -Libs: -L${libdir} -lOSMesa -Libs.private: -lm -lpthread -ldl -Cflags: -I${includedir} diff --git a/gl/lib/Linux/x86_64/pkgconfig/egl.pc b/gl/lib/Linux/x86_64/pkgconfig/egl.pc deleted file mode 100644 index 88255e814e..0000000000 --- a/gl/lib/Linux/x86_64/pkgconfig/egl.pc +++ /dev/null @@ -1,10 +0,0 @@ -prefix=/media/afaa385f-d818-4cfe-bec0-31ada40a8d36/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/dgles2/../lib/Linux/x86_64 -exec_prefix=${prefix} -libdir=${prefix}/lib -includedir=${prefix}/include - -Name: egl -Description: DGLES egl library -Version: 1.4.2 -Libs: -L${libdir} -lEGL -Cflags: -I${includedir} diff --git a/gl/lib/Linux/x86_64/pkgconfig/glesv1_cm.pc b/gl/lib/Linux/x86_64/pkgconfig/glesv1_cm.pc deleted file mode 100644 index 682d9d545b..0000000000 --- a/gl/lib/Linux/x86_64/pkgconfig/glesv1_cm.pc +++ /dev/null @@ -1,11 +0,0 @@ -prefix=/media/afaa385f-d818-4cfe-bec0-31ada40a8d36/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/dgles2/../lib/Linux/x86_64 -exec_prefix=${prefix} -libdir=${prefix}/lib -includedir=${prefix}/include - -Name: glesv1_cm -Description: DGLES OpenGL ES 1.1 CM library -Requires.private: egl -Version: 1.4.1 -Libs: -L${libdir} -lGLES_CM -Cflags: -I${includedir} diff --git a/gl/lib/Linux/x86_64/pkgconfig/glesv2.pc b/gl/lib/Linux/x86_64/pkgconfig/glesv2.pc deleted file mode 100644 index c620a2f393..0000000000 --- a/gl/lib/Linux/x86_64/pkgconfig/glesv2.pc +++ /dev/null @@ -1,12 +0,0 @@ -prefix=/media/afaa385f-d818-4cfe-bec0-31ada40a8d36/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/dgles2/../lib/Linux/x86_64 -exec_prefix=${prefix} -libdir=${prefix}/lib -includedir=${prefix}/include - -Name: glesv2 -Description: DGLES OpenGL ES 2.0 library -Requires.private: egl -Version: 2.0.0 -Libs: -L${libdir} -lGLESv2 -Cflags: -I${includedir} - diff --git a/gl/lib/Linux/x86_64/pkgconfig/osmesa.pc b/gl/lib/Linux/x86_64/pkgconfig/osmesa.pc deleted file mode 100644 index f2d07cab13..0000000000 --- a/gl/lib/Linux/x86_64/pkgconfig/osmesa.pc +++ /dev/null @@ -1,12 +0,0 @@ -prefix=/media/afaa385f-d818-4cfe-bec0-31ada40a8d36/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/mesa/../lib/Linux/x86_64 -exec_prefix=${prefix} -libdir=/media/afaa385f-d818-4cfe-bec0-31ada40a8d36/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/mesa/../lib/Linux/x86_64 -includedir=/media/afaa385f-d818-4cfe-bec0-31ada40a8d36/mackross/eclipse_linux_cdt_space/qemu_exynos4_gles/gl/mesa/../include - -Name: osmesa -Description: Mesa Off-screen Rendering library -Requires: -Version: 8.0.3 -Libs: -L${libdir} -lOSMesa -Libs.private: -lm -lpthread -ldl -Cflags: -I${includedir} diff --git a/hw/vga.c b/hw/vga.c index f82ced8e66..4401a82bdd 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -647,7 +647,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) } break; case VBE_DISPI_INDEX_XRES: - if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) { + if (val <= VBE_DISPI_MAX_XRES) { s->vbe_regs[s->vbe_index] = val; } break; diff --git a/package/build.macos-64 b/package/build.macos-64 index 5e845e106d..378f4fe904 100755 --- a/package/build.macos-64 +++ b/package/build.macos-64 @@ -3,11 +3,12 @@ clean() { prepare + set_build_env cd $SRCDIR/tizen if test -e "Makefile" then - ./emulator_configure.sh x86 + ./emulator_configure.sh x86 -ef "$BUILD_CFLAGS" make distclean fi rm -rf $SRCDIR/*.zip @@ -26,11 +27,24 @@ prepare() fi } +# libav build environment +set_build_env() +{ + PATH=$PATH:$ROOTDIR/bin + export PATH + + BUILD_CFLAGS=--extra-cflags="-I$ROOTDIR/include" + BUILD_CFLAGS+=--extra-cflags="-lyasm" + BUILD_CFLAGS+=--extra-cflags="-L$ROOTDIR/lib" +} + # build build() { + set_build_env + cd $SRCDIR/tizen/ - ./emulator_configure.sh x86 + ./emulator_configure.sh x86 -ef "$BUILD_CFLAGS" make all_dibs if [ $? -eq 0 ] then diff --git a/package/changelog b/package/changelog index 44984767ac..39a797752d 100644 --- a/package/changelog +++ b/package/changelog @@ -1,3 +1,395 @@ -* 2.2.0 -- tizen_2.2 source update -== Sangjin Kim 2013-06-24 +* 1.5.115 +- keep the touch point grabbing while finger rearranging +== GiWoong Kim 2013-10-30 +* 1.5.114 +- remove setInterpolation +== GiWoong Kim 2013-10-28 +* 1.5.113 +- fixed sync problem in the multi threading. +== Kitae Kim 2013-10-25 +* 1.5.112 +- Close opened camera fd when error occurs while maru camera starts +== Jinhyung Jo 2013-10-23 +* 1.5.111 +- disable gc interpolation for stretched image +== GiWoong Kim 2013-10-22 +* 1.5.110 +- fixed seek operation when decoding video. +== Kitae Kim 2013-10-18 +* 1.5.109 +- enable yasm option to use mmx feature on FFmpeg. +== Kitae Kim 2013-10-16 +* 1.5.108 +- remove memory leak on macosx +== Munkyu Im 2013-10-15 +* 1.5.107 +- fixed lock-up error when decoding video, especially on Windows. +== Kitae Kim 2013-10-14 +* 1.5.106 +- modified SDL_SetVideoMode flag +== GiWoong Kim 2013-10-14 +* 1.5.105 +- Added the error handling for dequeue webcam buffer +== Jinhyung Jo 2013-10-08 +* 1.5.104 +- added some logs in skin +== GiWoong Kim 2013-10-07 +* 1.5.103 +- Add install_name_tool rule for libcurl on MacOS +== Munkyu Im 2013-10-04 +* 1.5.102 +- clean-up memory release routine. +== Kitae Kim 2013-10-04 +* 1.5.101 +- fixed sync problem when closing codec context. +== Kitae Kim 2013-09-27 +* 1.5.100 +- menu blocking while touching +== GiWoong Kim 2013-09-27 +* 1.5.99 +- enable brillcodec device and disable old codec device. +== Kitae Kim 2013-09-25 +* 1.5.98 +- remove About and Preferences menu item +== Munkyu Im 2013-09-24 +* 1.5.97 +- release the touch event automatically +== GiWoong Kim 2013-09-17 +* 1.5.94 +- fix typo +== GiWoong Kim 2013-09-16 +* 1.5.89 +- no need to shell pack while layout changing +== GiWoong Kim 2013-09-06 +* 1.5.85 +- modified SDL logic +== GiWoong Kim 2013-09-05 +* 1.5.84 +- seperate a key event on Windows +== GiWoong Kim 2013-08-29 +* 1.5.82 +- modified qHD HwKey Region +== GiWoong Kim 2013-08-22 +* 1.5.81 +- modified sdb port +== GiWoong Kim 2013-08-21 +* 1.5.79 +- unified string utility functions as glib. +== GiWoong Kim 2013-08-20 +* 1.5.78 +- modified qHD dbi file +== GiWoong Kim 2013-08-20 +* 1.5.71 +- modified structure of virtio-hwkey +== Sungmin Ha 2013-07-25 +* 1.5.70 +- Support multiple linux dist when installing and remove qemu package. +== Kitae Kim 2013-07-17 +* 1.5.69 +- Version upgrade for pixmap bug. +== Sangjin Kim 2013-07-12 +* 1.5.68 +- Changed sh to bash in the install and remove script. +== Kitae Kim 2013-07-11 +* 1.5.67 +- Modified install and build script to apply TSUDO on Linux. +== Kitae Kim 2013-07-11 +* 1.5.66 +- Version upgrade for glXPixmap management bug. +== Sangjin Kim 2013-07-11 +* 1.5.65 +- Version upgrade for the fix of glXDestroyPixmap bug. +== Sangjin Kim 2013-07-09 +* 1.5.64 +- Version upgrade for the fix of gallery slideshow problem. +== Sangjin Kim 2013-07-08 +* 1.5.63 +- added sdbd_start protocol +== GiWoong Kim 2013-07-04 +* 1.5.62 +- Modified to reduce the spend-time when the display rotate/scale +- Added virtio config function to touchscreen device +== Jinhyung Jo 2013-07-02 +* 1.5.61 +- Rollback the loopback lookup code on Windows. +== Sangjin Kim 2013-06-30 +* 1.5.60 +- cancel a scrollbar timer +== GiWoong Kim 2013-06-29 +* 1.5.58 +- remove notifying to sdb server +== GiWoong Kim 2013-06-29 +* 1.5.57 +- keep the multi-touching when rotation +== GiWoong Kim 2013-06-26 +* 1.5.55 +- apply a custom scrollbar to KeyWindow +== GiWoong Kim 2013-06-24 +* 1.5.54 +- change the default skin type +== GiWoong Kim 2013-06-20 +* 1.5.53 +- position correction for emulator window +== GiWoong Kim 2013-06-19 +* 1.5.50 +- Modified the display to use the pixman library. +== Jinhyung Jo 2013-06-14 +* 1.5.49 +- modified keycode for 480x800-3btn +== GiWoong Kim 2013-06-13 +* 1.5.48 +- The KeyWindow has extended its docking area +== GiWoong Kim 2013-06-12 +* 1.5.45 +- changed the images of 3btn skin +== GiWoong Kim 2013-06-04 +* 1.5.44 +- added 3btn skins +== GiWoong Kim 2013-05-31 +* 1.5.43 +- Fixed a bug that appears horizontal flip images on Windows OS. +== Jinhyung Jo 2013-05-29 +* 1.5.42 +- Fixed a bug that appear a white region on the LCD. +== GiWoong Kim 2013-05-27 +* 1.5.41 +- erase unused variable in virtio-keyboard +== Sungmin Ha 2013-05-21 +* 1.5.38 +- modified process of using virtio keyboard queue and added key release event when context menu is activated +== Sungmin Ha 2013-05-14 +* 1.5.37 +- remove Open_Source_Announcement.txt file +== jihye kim 2013-05-09 + +* 1.5.36 +- call setBounds of display in arrangeSkin +== GiWoong Kim 2013-05-03 +* 1.5.35 +- dispose the framebuffer through syncExec +== GiWoong Kim 2013-05-02 +* 1.5.33 +- apply patch modified by Fengqian.Gao +== Sungmin Ha 2013-04-29 +* 1.5.32 +- Fix the slideshow problem of gallery app. +== Sangjin Kim 2013-04-23 +* 1.5.31 +- rollback 'optimize a framebuffer copying' +== GiWoong Kim 2013-04-18 +* 1.5.28 +- Fix pBuffer issue for xcomposite. +== Sangjin Kim 2013-04-16 +* 1.5.27 +- Change the FB configs limitaion from 10 to 32 for each process. +== Sangjin Kim 2013-04-12 +* 1.5.26 +- Add glFinish() after AGL function aglTexImagePBuffer() cause of pbuffer bug on MAC os. +== Sangjin Kim 2013-04-11 +* 1.5.25 +- Do not exit if log directory is deleted on runtime. +== Seokyeon Hwang 2013-04-10 +* 1.5.24 +- Verify the passed texture ID in glBindTexture_func. If ID is invalid, do nothing. +== Sangjin Kim 2013-04-09 +* 1.5.23 +- increased virtio keyboard queue and fixed overwrite bug +== SungMin Ha 2013-04-06 +* 1.5.22 +- no need to get the shmkey from another shm +== GiWoong Kim 2013-04-02 +* 1.5.21 +- Fixed a bug that a camera frame is not sent to FW. +== Jinhyung Jo 2013-03-29 +* 1.5.20 +- modified skin's dbi file for key code of phone shape +== Sungmin Ha 2013-03-29 +* 1.5.19 +- modified elem index and mutex lock in virtio-kbd +== Sungmin Ha 2013-03-29 +* 1.5.18 +- Skip the display updates until the LCD is turned off +== GiWoong Kim 2013-03-28 +* 1.5.17 +- modified Makefile to library load on mac from check-gl +== Sungmin Ha 2013-03-26 +* 1.5.16 +- Fix dibs install error by mis-typing. +== Sangjin Kim 2013-03-25 +* 1.5.15 +- Fix dibs build error. +== Sangjin Kim 2013-03-21 +* 1.5.14 +- Generate check-gl binary to use at an emulator-manager. +== Sangjin Kim 2013-03-21 +* 1.5.13 +- Enable pbuffer surface. +== Sangjin Kim 2013-03-20 +* 1.5.6 +- modified virtio hwkey device and improved hwkey mapping +== Sungmin Ha 2013-03-20 +* 1.5.5 +- moved kvm script files from qemu-common to qemu-x86 package. +== Kitae Kim 2013-03-15 +* 1.5.4 +- added routine in case that there is no gksudo. +== Kitae Kim 2013-03-08 +* 1.5.03 +- modified path separator +== GiWoong Kim 2013-02-25 +* 1.5.02 +- Sync-up with tizen 2.0 latest gl source code. +== Sangjin Kim 2013-02-21 +* 1.5.01 +- added virtio hwkey device +== GiWoong Kim 2013-02-21 +* 1.4.90 +- version up +== SungMin Ha 2013-02-15 +* 1.4.89 +- added bottom half instead of mloop +== GiWoong Kim 2013-02-15 +* 1.4.80 +- version up for making new package +== Munkyu Im 2013-02-04 +* 1.4.79 +- added pthread_mutex_destroy +== GiWoong Kim 2013-01-29 +* 1.4.76 +- prepare 10 colors for Pair Tag +== GiWoong Kim 2013-01-25 +* 1.4.67 +- Changed host keyboard status routine on OS X. +== Kitae Kim 2013-01-24 +* 1.4.66 +- modified screenshot operation when vga is not ready +== Sungmin Ha 2013-01-23 +* 1.4.65 +- version up for making new package +== Munkyu Im 2013-01-22 +* 1.4.64 +- Fix emulator crash problem when using EffectsApp. +== Sangjin Kim 2013-01-17 +* 1.4.62 +- removed ifndef for screenshot +== Sungmin Ha 2013-01-17 +* 1.4.61 +- Fixed a problem about displayed useless line on screenshot +== Sungmin Ha 2013-01-16 +* 1.4.60 +- removed setFocus on mac +== GiWoong Kim 2013-01-16 +* 1.4.58 +- modify init process +== Munkyu Im 2013-01-16 +* 1.4.57 +- modified include path +== GiWoong Kim 2013-01-15 +* 1.4.55 +- move SDL_gfx files +== GiWoong Kim 2013-01-15 +* 1.4.51 +- control the focus in general skin +== GiWoong Kim 2013-01-14 +* 1.4.49 +- switch the z-order between main window and key window +== GiWoong Kim 2013-01-11 +* 1.4.43 +- change temp file path +== Munkyu Im 2013-01-09 +* 1.4.42 +- fix dynamic loading library path +== Munkyu Im 2013-01-04 +* 1.4.41 +- fix multi touch on Mac +== Munkyu Im 2013-01-03 +* 1.4.40 +- version up +== Munkyu Im 2013-01-03 +* 1.4.39 +- version up +== Sooyoung Ha 2013-01-03 +* 1.4.38 +- Fixed a memory leak while decoding video. +== Kitae Kim 2012-12-28 +* 1.4.35 +- fix gl capability check fail on windows intel graphics machine. +== Sangjin Kim 2012-12-28 +* 1.4.34 +- fix getting proxy +== Munkyu Im 2012-12-27 +* 1.4.33 +- Fixed codec module and added function declarations for virtio-keyboard. +== Kitae Kim 2012-12-18 +* 1.4.32 +- Copy sdbscript file to bin folder on mac. +== GiWoong Kim 2012-12-18 +* 1.4.25 +- Fixed a capture failure on Linux system. +== Jinhyung Jo 2012-12-17 +* 1.4.24 +- Reverted dibs build script. +- The previous build script was wrong. +== Kitae Kim 2012-12-17 +* 1.4.23 +- Fixed an unexpected termination on Windows while previewing camera. +== Jinhyung Jo 2012-12-17 +* 1.4.22 +- Added multi-touch control scenario +== GiWoong Kim 2012-12-10 +* 1.4.17 +- Added double quotation mark for path. +== GiWoong Kim 2012-12-06 +* 1.4.15 +- rearrange finger image when rotate +== Munkyu In 2012-11-29 +* 1.4.14 +- added try-catch to AboutDialog +== GiWoong Kim 2012-11-29 +* 1.4.13 +- Text dimming issue fixed at windows with nvidia card. +== Sangjin Kim 2012-11-28 +* 1.4.12 +- Convert a HW key container in general skin +== GiWoong Kim 2012-11-26 +* 1.4.9 +- Fix EGL_BAD_ALLOC error when using pixmap surface repeatedly. +== Sangjin Kim 2012-11-22 +* 1.4.8 +- Added force close menu +- Advanced>Force Close +== GiWoong Kim 2012-11-12 +* 1.4.7 +- Fixed a bug of brightness level +== Jinhyung Jo 2012-11-15 +* 1.4.6 +- refactoring of skin code +- Fixed N_SE-12805 issue +== GiWoong Kim 2012-11-14 +* 1.4.5 +- refactoring of skin code +- Added EmulatorSkinState file & define ISkinComposer interface +== GiWoong Kim 2012-11-12 +* 1.4.4 +- Apply qemu_ld/st optimization according to QEMU 1.2 +== Yeongkyoon Lee 2012-11-09 +* 1.4.2 +- Added libattr1-dev, libcap library +- Added libattr1-dev, libcap library +== GiWoong Kim 2012-11-08 +* 1.4.1 +- Disable folding button in general skin +- Disable folding button in general skin +== GiWoong Kim 2012-11-06 +* 1.4.0 +- vga: Support HVGA, WXGA, HD1080, WQXGA resolution. +- Support HVGA, WXGA, HD1080, WQXGA resolution. +== Signed-off-by: Sangjin Kim 2012-11-02 +* 1.3.68 +- Don't lose the release event of HW key +- Event if user releases the mouse cursor at outside of HW key area, it does not lose the event. +== GiWoong Kim 2012-10-29 +* 1.3.66 +- Change SDK version. +- Change version from 2.0a3 to 2.0a4-RC1 +== Kitae Kim 2012-10-23 diff --git a/package/emulator-qemu-x86.install.ubuntu-32 b/package/emulator-qemu-x86.install.ubuntu-32 index d84e1dc4c4..66b5a3b98a 100755 --- a/package/emulator-qemu-x86.install.ubuntu-32 +++ b/package/emulator-qemu-x86.install.ubuntu-32 @@ -1,40 +1,52 @@ #!/bin/bash -ex -TIZEN_SDK_INSTALL_PATH=`echo $INSTALLED_PATH` -if [ -z $TIZEN_SDK_INSTALL_PATH ] +TIZEN_SDK_INSTALL_PATH=`echo ${INSTALLED_PATH}` +if [ -z ${TIZEN_SDK_INSTALL_PATH} ] then # echo "There is no TIZEN_SDK_PATH ENV" >> /tmp/emulator.log exit 2; fi -if [ -e /etc/os-release ]; then - OS_NAME=`cat /etc/os-release | grep ID | head -n 1 | awk -F= '{print $2}'` +LSB_RELEASE=`which lsb_release` +if [ "${LSB_RELEASE}" = "" ]; then + if [ -e /etc/os-release ]; then + OS_NAME=`cat /etc/os-release | grep ID | head -n 1 | awk -F= '{print $2}'` + fi + # TODO: Detect other linux distributions. +else + OS_NAME=`lsb_release --id --short` +fi + +if [ ! -z "${OS_NAME}" ]; then + OS_NAME=`echo ${OS_NAME} | tr '[:upper:]' '[:lower:]'` fi +echo "Linux Distribution: ${OS_NAME}" TMP_FILE=init_tizen-kvm.sh -echo "cp ${TIZEN_SDK_INSTALL_PATH}/tools/emulator/etc/tizen-kvm /etc/init.d/" >> $TMP_FILE -echo "cp ${TIZEN_SDK_INSTALL_PATH}/tools/emulator/etc/45-tizen-kvm.rules /lib/udev/rules.d/" >> $TMP_FILE -echo "/etc/init.d/tizen-kvm start" >> $TMP_FILE +echo "#!/bin/bash -ex" >> ${TMP_FILE} +echo "cp ${TIZEN_SDK_INSTALL_PATH}/tools/emulator/etc/tizen-kvm /etc/init.d/" >> ${TMP_FILE} +echo "cp ${TIZEN_SDK_INSTALL_PATH}/tools/emulator/etc/45-tizen-kvm.rules /lib/udev/rules.d/" >> ${TMP_FILE} +echo "/etc/init.d/tizen-kvm start" >> ${TMP_FILE} if [ "ubuntu" = "${OS_NAME}" ] ; then - echo "update-rc.d tizen-kvm defaults" >> $TMP_FILE + echo "update-rc.d tizen-kvm defaults" >> ${TMP_FILE} fi -chmod +x $TMP_FILE +chmod +x ${TMP_FILE} -if [ "$TSUDO" != "" ] # since installer v2.27 +if [ "${TSUDO}" != "" ] # since installer v2.27 then TSUDO_MSG="Enter your password to enable kvm module if your machine supports hardware virtualization." TMP_PATH="`pwd`/${TMP_FILE}" - $TSUDO -m "${TSUDO_MSG}" sh $TMP_PATH + ${TSUDO} -m "${TSUDO_MSG}" sh ${TMP_PATH} else GKSUDO=`which gksudo` - if [ "$GKSUDO" = "" ] + if [ "${GKSUDO}" = "" ] then echo "there is no gksudo." - sudo ./$TMP_FILE + sudo ./${TMP_FILE} else - gksudo ./$TMP_FILE + gksudo ./${TMP_FILE} fi fi -rm $TMP_FILE +rm ${TMP_FILE} diff --git a/package/emulator-qemu-x86.install.ubuntu-64 b/package/emulator-qemu-x86.install.ubuntu-64 index d84e1dc4c4..66b5a3b98a 100755 --- a/package/emulator-qemu-x86.install.ubuntu-64 +++ b/package/emulator-qemu-x86.install.ubuntu-64 @@ -1,40 +1,52 @@ #!/bin/bash -ex -TIZEN_SDK_INSTALL_PATH=`echo $INSTALLED_PATH` -if [ -z $TIZEN_SDK_INSTALL_PATH ] +TIZEN_SDK_INSTALL_PATH=`echo ${INSTALLED_PATH}` +if [ -z ${TIZEN_SDK_INSTALL_PATH} ] then # echo "There is no TIZEN_SDK_PATH ENV" >> /tmp/emulator.log exit 2; fi -if [ -e /etc/os-release ]; then - OS_NAME=`cat /etc/os-release | grep ID | head -n 1 | awk -F= '{print $2}'` +LSB_RELEASE=`which lsb_release` +if [ "${LSB_RELEASE}" = "" ]; then + if [ -e /etc/os-release ]; then + OS_NAME=`cat /etc/os-release | grep ID | head -n 1 | awk -F= '{print $2}'` + fi + # TODO: Detect other linux distributions. +else + OS_NAME=`lsb_release --id --short` +fi + +if [ ! -z "${OS_NAME}" ]; then + OS_NAME=`echo ${OS_NAME} | tr '[:upper:]' '[:lower:]'` fi +echo "Linux Distribution: ${OS_NAME}" TMP_FILE=init_tizen-kvm.sh -echo "cp ${TIZEN_SDK_INSTALL_PATH}/tools/emulator/etc/tizen-kvm /etc/init.d/" >> $TMP_FILE -echo "cp ${TIZEN_SDK_INSTALL_PATH}/tools/emulator/etc/45-tizen-kvm.rules /lib/udev/rules.d/" >> $TMP_FILE -echo "/etc/init.d/tizen-kvm start" >> $TMP_FILE +echo "#!/bin/bash -ex" >> ${TMP_FILE} +echo "cp ${TIZEN_SDK_INSTALL_PATH}/tools/emulator/etc/tizen-kvm /etc/init.d/" >> ${TMP_FILE} +echo "cp ${TIZEN_SDK_INSTALL_PATH}/tools/emulator/etc/45-tizen-kvm.rules /lib/udev/rules.d/" >> ${TMP_FILE} +echo "/etc/init.d/tizen-kvm start" >> ${TMP_FILE} if [ "ubuntu" = "${OS_NAME}" ] ; then - echo "update-rc.d tizen-kvm defaults" >> $TMP_FILE + echo "update-rc.d tizen-kvm defaults" >> ${TMP_FILE} fi -chmod +x $TMP_FILE +chmod +x ${TMP_FILE} -if [ "$TSUDO" != "" ] # since installer v2.27 +if [ "${TSUDO}" != "" ] # since installer v2.27 then TSUDO_MSG="Enter your password to enable kvm module if your machine supports hardware virtualization." TMP_PATH="`pwd`/${TMP_FILE}" - $TSUDO -m "${TSUDO_MSG}" sh $TMP_PATH + ${TSUDO} -m "${TSUDO_MSG}" sh ${TMP_PATH} else GKSUDO=`which gksudo` - if [ "$GKSUDO" = "" ] + if [ "${GKSUDO}" = "" ] then echo "there is no gksudo." - sudo ./$TMP_FILE + sudo ./${TMP_FILE} else - gksudo ./$TMP_FILE + gksudo ./${TMP_FILE} fi fi -rm $TMP_FILE +rm ${TMP_FILE} diff --git a/package/emulator-qemu-x86.remove.ubuntu-32 b/package/emulator-qemu-x86.remove.ubuntu-32 index 05e72fefb1..f94faafdb4 100755 --- a/package/emulator-qemu-x86.remove.ubuntu-32 +++ b/package/emulator-qemu-x86.remove.ubuntu-32 @@ -1,39 +1,51 @@ #!/bin/bash -ex -TIZEN_SDK_INSTALL_PATH=`echo $INSTALLED_PATH` -if [ -z $TIZEN_SDK_INSTALL_PATH ] +TIZEN_SDK_INSTALL_PATH=`echo ${INSTALLED_PATH}` +if [ -z ${TIZEN_SDK_INSTALL_PATH} ] then # echo "There is no TIZEN_SDK_PATH ENV" >> /tmp/emulator.log exit 2; fi -if [ -e /etc/os-release ]; then - OS_NAME=`cat /etc/os-release | grep ID | head -n 1 | awk -F= '{print $2}'` +LSB_RELEASE=`which lsb_release` +if [ "${LSB_RELEASE}" = "" ]; then + if [ -e /etc/os-release ]; then + OS_NAME=`cat /etc/os-release | grep ID | head -n 1 | awk -F= '{print $2}'` + fi + # TODO: Detect other linux distributions. +else + OS_NAME=`lsb_release --id --short` +fi + +if [ ! -z "${OS_NAME}" ]; then + OS_NAME=`echo ${OS_NAME} | tr '[:upper:]' '[:lower:]'` fi +echo "Linux Distribution: ${OS_NAME}" TMP_FILE=remove_tizen-kvm.sh +echo "#!/bin/bash -ex" >> ${TMP_FILE} if [ "ubuntu" = "${OS_NAME}" ] ; then - echo "update-rc.d -f tizen-kvm remove" >> $TMP_FILE + echo "update-rc.d -f tizen-kvm remove" >> ${TMP_FILE} fi -echo "rm -f /etc/init.d/tizen-kvm" >> $TMP_FILE -echo "rm -f /lib/udev/rules.d/45-tizen-kvm.rules" >> $TMP_FILE +echo "rm -f /etc/init.d/tizen-kvm" >> ${TMP_FILE} +echo "rm -f /lib/udev/rules.d/45-tizen-kvm.rules" >> ${TMP_FILE} -chmod +x $TMP_FILE +chmod +x ${TMP_FILE} -if [ "$TSUDO" != "" ] # since installer v2.27 +if [ "${TSUDO}" != "" ] # since installer v2.27 then TSUDO_MSG="Enter your password to remove /etc/init.d/tizen-kvm." TMP_PATH="`pwd`/${TMP_FILE}" - $TSUDO -m "${TSUDO_MSG}" sh $TMP_PATH + $TSUDO -m "${TSUDO_MSG}" sh ${TMP_PATH} else GKSUDO=`which gksudo` - if [ "$GKSUDO" = "" ] + if [ "${GKSUDO}" = "" ] then echo "there is no gksudo." - sudo ./$TMP_FILE + sudo ./${TMP_FILE} else - gksudo ./$TMP_FILE + gksudo ./${TMP_FILE} fi fi -rm $TMP_FILE +rm ${TMP_FILE} diff --git a/package/emulator-qemu-x86.remove.ubuntu-64 b/package/emulator-qemu-x86.remove.ubuntu-64 index 05e72fefb1..f94faafdb4 100755 --- a/package/emulator-qemu-x86.remove.ubuntu-64 +++ b/package/emulator-qemu-x86.remove.ubuntu-64 @@ -1,39 +1,51 @@ #!/bin/bash -ex -TIZEN_SDK_INSTALL_PATH=`echo $INSTALLED_PATH` -if [ -z $TIZEN_SDK_INSTALL_PATH ] +TIZEN_SDK_INSTALL_PATH=`echo ${INSTALLED_PATH}` +if [ -z ${TIZEN_SDK_INSTALL_PATH} ] then # echo "There is no TIZEN_SDK_PATH ENV" >> /tmp/emulator.log exit 2; fi -if [ -e /etc/os-release ]; then - OS_NAME=`cat /etc/os-release | grep ID | head -n 1 | awk -F= '{print $2}'` +LSB_RELEASE=`which lsb_release` +if [ "${LSB_RELEASE}" = "" ]; then + if [ -e /etc/os-release ]; then + OS_NAME=`cat /etc/os-release | grep ID | head -n 1 | awk -F= '{print $2}'` + fi + # TODO: Detect other linux distributions. +else + OS_NAME=`lsb_release --id --short` +fi + +if [ ! -z "${OS_NAME}" ]; then + OS_NAME=`echo ${OS_NAME} | tr '[:upper:]' '[:lower:]'` fi +echo "Linux Distribution: ${OS_NAME}" TMP_FILE=remove_tizen-kvm.sh +echo "#!/bin/bash -ex" >> ${TMP_FILE} if [ "ubuntu" = "${OS_NAME}" ] ; then - echo "update-rc.d -f tizen-kvm remove" >> $TMP_FILE + echo "update-rc.d -f tizen-kvm remove" >> ${TMP_FILE} fi -echo "rm -f /etc/init.d/tizen-kvm" >> $TMP_FILE -echo "rm -f /lib/udev/rules.d/45-tizen-kvm.rules" >> $TMP_FILE +echo "rm -f /etc/init.d/tizen-kvm" >> ${TMP_FILE} +echo "rm -f /lib/udev/rules.d/45-tizen-kvm.rules" >> ${TMP_FILE} -chmod +x $TMP_FILE +chmod +x ${TMP_FILE} -if [ "$TSUDO" != "" ] # since installer v2.27 +if [ "${TSUDO}" != "" ] # since installer v2.27 then TSUDO_MSG="Enter your password to remove /etc/init.d/tizen-kvm." TMP_PATH="`pwd`/${TMP_FILE}" - $TSUDO -m "${TSUDO_MSG}" sh $TMP_PATH + $TSUDO -m "${TSUDO_MSG}" sh ${TMP_PATH} else GKSUDO=`which gksudo` - if [ "$GKSUDO" = "" ] + if [ "${GKSUDO}" = "" ] then echo "there is no gksudo." - sudo ./$TMP_FILE + sudo ./${TMP_FILE} else - gksudo ./$TMP_FILE + gksudo ./${TMP_FILE} fi fi -rm $TMP_FILE +rm ${TMP_FILE} diff --git a/package/pkginfo.manifest b/package/pkginfo.manifest index b14c1a4687..9e7001d5d6 100644 --- a/package/pkginfo.manifest +++ b/package/pkginfo.manifest @@ -1,4 +1,4 @@ -Version: 2.2.0 +Version: 1.5.115 Maintainer: Yeong-Kyoon Lee Source: emulator @@ -17,13 +17,13 @@ Description: Common binaries for Tizen Emulator Package: emulator-qemu-common OS: windows-32, windows-64 Build-host-os: windows-32 -Build-dependency: emulator-lib [ windows-32 ] +Build-dependency: emulator-lib [ windows-32 ], yasm [ windows-32 ] Description: Common binaries for Tizen Emulator Package: emulator-qemu-common OS: macos-64 Build-host-os: macos-64 -Build-dependency: emulator-lib [ macos-64 ] +Build-dependency: emulator-lib [ macos-64 ], yasm [ macos-64 ] Description: Common binaries for Tizen Emulator Package: emulator-qemu-x86 @@ -43,13 +43,13 @@ Description: Tizen x86 Emulator Package: emulator-qemu-x86 OS: windows-32, windows-64 Build-host-os: windows-32 -Build-dependency: SDL-1.2.14 [ windows-32 ], apache-ant-1.8.3-bin [ windows-32 ], gtk-bundle_2.16.6 [ windows-32 ], directx-dev [ windows-32 ], libcurl-4 [ windows-32 ], pixman-0.30.0 [ windows-32 ], emulator-lib [ windows-32 ] +Build-dependency: SDL-1.2.14 [ windows-32 ], apache-ant-1.8.3-bin [ windows-32 ], gtk-bundle_2.16.6 [ windows-32 ], directx-dev [ windows-32 ], libcurl-4 [ windows-32 ], pixman-0.30.0 [ windows-32 ], emulator-lib [ windows-32 ], yasm [ windows-32 ] Install-dependency: emulator-kernel-x86 [ windows-32 ], vgabios [ windows-32 ] Description: Tizen x86 Emulator Package: emulator-qemu-x86 OS: macos-64 Build-host-os: macos-64 -Build-dependency: emulator-lib [ macos-64 ] +Build-dependency: emulator-lib [ macos-64 ], yasm [ macos-64 ] Install-dependency: emulator-kernel-x86 [ macos-64 ], vgabios [ macos-64 ] Description: Tizen x86 Emulator diff --git a/qemu-sockets.c b/qemu-sockets.c index 34cbbde01a..27d0c90db3 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -243,11 +243,13 @@ int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp) ai.ai_family = PF_INET6; #ifdef CONFIG_MARU + #if !defined(_WIN32) // for lookup loopback interface... if (addr[0] == '\0') { ai.ai_flags = 0; addr = NULL; } + #endif #endif /* lookup */ diff --git a/tizen/distrib/initscript/tizen_kvm b/tizen/distrib/initscript/tizen_kvm deleted file mode 100755 index 263a687d2a..0000000000 --- a/tizen/distrib/initscript/tizen_kvm +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -do_start () { - if grep -qs "^flags.* vmx" /proc/cpuinfo; then - modprobe -b kvm_intel "$KVM_NESTED" - elif grep -qs "^flags.* svm" /proc/cpuinfo; then - modprobe -b kvm_amd - fi -} - -case "$1" in - start) - do_start - ;; - restart|reload|force-reload) - # No-op - ;; - stop) - # No-op - ;; - *) - echo "Usage: $0 start|stop" >&2 - exit 3 - ;; -esac diff --git a/tizen/distrib/libav/libavcodec/libavcodec.v b/tizen/distrib/libav/libavcodec/libavcodec.v deleted file mode 100644 index 65699038ab..0000000000 --- a/tizen/distrib/libav/libavcodec/libavcodec.v +++ /dev/null @@ -1,9 +0,0 @@ -LIBAVCODEC_$MAJOR { - global: *; - local: - ff_*_bsf; - ff_*_decoder; - ff_*_encoder; - ff_*_hwaccel; - ff_*_parser; -}; diff --git a/tizen/distrib/libav/libavcodec/version.h b/tizen/distrib/libav/libavcodec/version.h deleted file mode 100644 index aded68e83e..0000000000 --- a/tizen/distrib/libav/libavcodec/version.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_VERSION_H -#define AVCODEC_VERSION_H - -#define LIBAVCODEC_VERSION_MAJOR 53 -#define LIBAVCODEC_VERSION_MINOR 5 -#define LIBAVCODEC_VERSION_MICRO 0 - -#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ - LIBAVCODEC_VERSION_MINOR, \ - LIBAVCODEC_VERSION_MICRO) -#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ - LIBAVCODEC_VERSION_MINOR, \ - LIBAVCODEC_VERSION_MICRO) -#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT - -#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) - -/** - * Those FF_API_* defines are not part of public API. - * They may change, break or disappear at any time. - */ -#ifndef FF_API_PALETTE_CONTROL -#define FF_API_PALETTE_CONTROL (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_OLD_SAMPLE_FMT -#define FF_API_OLD_SAMPLE_FMT (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_OLD_AUDIOCONVERT -#define FF_API_OLD_AUDIOCONVERT (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_ANTIALIAS_ALGO -#define FF_API_ANTIALIAS_ALGO (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_REQUEST_CHANNELS -#define FF_API_REQUEST_CHANNELS (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_OPT_H -#define FF_API_OPT_H (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_THREAD_INIT -#define FF_API_THREAD_INIT (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_OLD_FF_PICT_TYPES -#define FF_API_OLD_FF_PICT_TYPES (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_FLAC_GLOBAL_OPTS -#define FF_API_FLAC_GLOBAL_OPTS (LIBAVCODEC_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_GET_PIX_FMT_NAME -#define FF_API_GET_PIX_FMT_NAME (LIBAVCODEC_VERSION_MAJOR < 54) -#endif - -#endif /* AVCODEC_VERSION_H */ diff --git a/tizen/distrib/libav/libavdevice/libavdevice.v b/tizen/distrib/libav/libavdevice/libavdevice.v deleted file mode 100644 index 663af85ba8..0000000000 --- a/tizen/distrib/libav/libavdevice/libavdevice.v +++ /dev/null @@ -1,4 +0,0 @@ -LIBAVDEVICE_$MAJOR { - global: avdevice_*; - local: *; -}; diff --git a/tizen/distrib/libav/libavfilter/libavfilter.v b/tizen/distrib/libav/libavfilter/libavfilter.v deleted file mode 100644 index 83e8887080..0000000000 --- a/tizen/distrib/libav/libavfilter/libavfilter.v +++ /dev/null @@ -1,4 +0,0 @@ -LIBAVFILTER_$MAJOR { - global: avfilter_*; av_*; - local: *; -}; diff --git a/tizen/distrib/libav/libavformat/libavformat.v b/tizen/distrib/libav/libavformat/libavformat.v deleted file mode 100644 index 0ec1c3c4de..0000000000 --- a/tizen/distrib/libav/libavformat/libavformat.v +++ /dev/null @@ -1,7 +0,0 @@ -LIBAVFORMAT_$MAJOR { - global: *; - local: - ff_*_demuxer; - ff_*_muxer; - ff_*_protocol; -}; diff --git a/tizen/distrib/libav/libavformat/version.h b/tizen/distrib/libav/libavformat/version.h deleted file mode 100644 index 3cc1718f2b..0000000000 --- a/tizen/distrib/libav/libavformat/version.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Version macros. - * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Libav is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFORMAT_VERSION_H -#define AVFORMAT_VERSION_H - -#include "libavutil/avutil.h" - -#define LIBAVFORMAT_VERSION_MAJOR 53 -#define LIBAVFORMAT_VERSION_MINOR 2 -#define LIBAVFORMAT_VERSION_MICRO 0 - -#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ - LIBAVFORMAT_VERSION_MINOR, \ - LIBAVFORMAT_VERSION_MICRO) -#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \ - LIBAVFORMAT_VERSION_MINOR, \ - LIBAVFORMAT_VERSION_MICRO) -#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT - -#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) - -/** - * Those FF_API_* defines are not part of public API. - * They may change, break or disappear at any time. - */ -#ifndef FF_API_OLD_METADATA2 -#define FF_API_OLD_METADATA2 (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_READ_SEEK -#define FF_API_READ_SEEK (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_OLD_AVIO -#define FF_API_OLD_AVIO (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_DUMP_FORMAT -#define FF_API_DUMP_FORMAT (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_PARSE_DATE -#define FF_API_PARSE_DATE (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_FIND_INFO_TAG -#define FF_API_FIND_INFO_TAG (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_PKT_DUMP -#define FF_API_PKT_DUMP (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_GUESS_IMG2_CODEC -#define FF_API_GUESS_IMG2_CODEC (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_SDP_CREATE -#define FF_API_SDP_CREATE (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_FORMAT_PARAMETERS -#define FF_API_FORMAT_PARAMETERS (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif -#ifndef FF_API_FLAG_RTP_HINT -#define FF_API_FLAG_RTP_HINT (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif - -#endif /* AVFORMAT_VERSION_H */ diff --git a/tizen/distrib/libav/libavutil/libavutil.v b/tizen/distrib/libav/libavutil/libavutil.v deleted file mode 100644 index ec52f2be7a..0000000000 --- a/tizen/distrib/libav/libavutil/libavutil.v +++ /dev/null @@ -1,4 +0,0 @@ -LIBAVUTIL_$MAJOR { - global: av_*; ff_*; avutil_*; - local: *; -}; diff --git a/tizen/distrib/libav/libpostproc/libpostproc.v b/tizen/distrib/libav/libpostproc/libpostproc.v deleted file mode 100644 index e65d76f4f6..0000000000 --- a/tizen/distrib/libav/libpostproc/libpostproc.v +++ /dev/null @@ -1,4 +0,0 @@ -LIBPOSTPROC_$MAJOR { - global: postproc_*; pp_*; - local: *; -}; diff --git a/tizen/distrib/libav/libswscale/libswscale.v b/tizen/distrib/libav/libswscale/libswscale.v deleted file mode 100644 index c68f153cbc..0000000000 --- a/tizen/distrib/libav/libswscale/libswscale.v +++ /dev/null @@ -1,4 +0,0 @@ -LIBSWSCALE_$MAJOR { - global: swscale_*; sws_*; ff_*; - local: *; -}; diff --git a/tizen/emulator_configure.sh b/tizen/emulator_configure.sh index eeb1b63159..7d39413b6e 100755 --- a/tizen/emulator_configure.sh +++ b/tizen/emulator_configure.sh @@ -6,6 +6,7 @@ VIRTIOGL_EN="" OPENGLES_EN="" YAGL_EN="" YAGL_STATS_EN="" +FFMPEG_CONFIGURE_APPEND="" usage() { echo "usage: build.sh [options] [target]" @@ -28,6 +29,8 @@ usage() { echo " enable YaGL stats" echo "-e|--extra" echo " extra options for QEMU configure" + echo "-ef|--extra-ffmpeg" + echo " extra options for FFmpeg configure" echo "-u|-h|--help|--usage" echo " display this help message and exit" } @@ -158,6 +161,10 @@ do shift CONFIGURE_APPEND="$CONFIGURE_APPEND $1" ;; + -ef|--extra-ffmpeg) + shift + FFMPEG_CONFIGURE_APPEND="$FFMPEG_CONFIGURE_APPEND $1" + ;; -vgl|--virtio-gl) virtgl_enable 1 ;; @@ -219,7 +226,7 @@ cd distrib/libav echo "" echo "##### FFMPEG configure for emulator" ./configure \ - --prefix=./$bindir --arch=${ffmpegarc} --enable-static --enable-pic --enable-optimizations --disable-doc --disable-gpl --disable-yasm --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1 + --prefix=./$bindir --arch=${ffmpegarc} --enable-static --enable-pic --enable-optimizations --disable-doc --disable-gpl --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1 cd ../.. cd .. @@ -242,7 +249,7 @@ cd distrib/libav echo "" echo "##### FFMPEG configure for emulator" ./configure \ - --prefix=./$bindir --arch=x86 --enable-static --enable-w32threads --enable-optimizations --enable-memalign-hack --disable-doc --disable-gpl --disable-yasm --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1 + --prefix=./$bindir --arch=x86 --enable-static --enable-w32threads --enable-optimizations --enable-memalign-hack --disable-doc --disable-gpl --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1 cd ../.. cd .. @@ -267,7 +274,7 @@ cd distrib/libav echo "" echo "##### FFMPEG configure for emulator" ./configure \ ---prefix=./$bindir --extra-cflags=-mmacosx-version-min=10.4 --arch=x86 --enable-static --enable-pic --enable-optimizations --disable-doc --disable-gpl --disable-yasm --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1 --cc=cc +--prefix=./$bindir --extra-cflags=-mmacosx-version-min=10.4 --arch=${ffmpegarc} --enable-static --enable-pic --enable-optimizations --disable-doc --disable-gpl --disable-postproc --disable-swscale --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-ffplay --disable-decoders --disable-encoders --disable-muxers --disable-demuxers --disable-parsers --disable-protocols --disable-network --disable-bsfs --disable-devices --disable-filters --enable-encoder=h263 --enable-encoder=h263p --enable-encoder=mpeg4 --enable-encoder=msmpeg4v2 --enable-encoder=msmpeg4v3 --enable-decoder=aac --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mpeg4 --enable-decoder=mpegvideo --enable-decoder=msmpeg4v1 --enable-decoder=msmpeg4v2 --enable-decoder=msmpeg4v3 --enable-decoder=wmav1 --enable-decoder=wmav2 --enable-decoder=wmv3 --enable-decoder=vc1 --cc=cc $FFMPEG_CONFIGURE_APPEND cd ../.. cd .. diff --git a/tizen/src/Makefile b/tizen/src/Makefile old mode 100755 new mode 100644 index 15d84a7e12..bfb5f843d9 --- a/tizen/src/Makefile +++ b/tizen/src/Makefile @@ -151,6 +151,7 @@ ifdef CONFIG_DARWIN install_name_tool -change /opt/local/lib/gcc47/libgcc_s.1.dylib @loader_path/libgcc_s.1.dylib $(EMUL_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libz.1.dylib @loader_path/libz.1.dylib $(EMUL_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(EMUL_DIR)/bin/qemu-img + install_name_tool -change /usr/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(EMUL_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libglib-2.0.*.dylib @loader_path/libglib-2.0.0.dylib $(EMUL_DIR)/bin/check-gl install_name_tool -change /opt/local/lib/libintl.8.dylib @loader_path/libintl.8.dylib $(EMUL_DIR)/bin/check-gl install_name_tool -change /opt/local/lib/gcc47/libgcc_s.1.dylib @loader_path/libgcc_s.1.dylib $(EMUL_DIR)/bin/check-gl @@ -165,6 +166,7 @@ ifdef CONFIG_DARWIN install_name_tool -change /opt/local/lib/libz.1.dylib @loader_path/libz.1.dylib $(EMUL_DIR)/bin/emulator-x86 ;\ install_name_tool -change /opt/local/lib/libncurses.5.dylib @loader_path/libncurses.5.dylib $(EMUL_DIR)/bin/emulator-x86 ;\ install_name_tool -change /opt/local/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(EMUL_DIR)/bin/emulator-x86 ;\ + install_name_tool -change /usr/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(EMUL_DIR)/bin/emulator-x86 ;\ ;; \ arm-softmmu) \ ;; \ @@ -265,6 +267,7 @@ ifdef CONFIG_DARWIN install_name_tool -change /opt/local/lib/gcc47/libgcc_s.1.dylib @loader_path/libgcc_s.1.dylib $(DIBS_COMMON_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libz.1.dylib @loader_path/libz.1.dylib $(DIBS_COMMON_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(DIBS_COMMON_DIR)/bin/qemu-img + install_name_tool -change /usr/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(DIBS_COMMON_DIR)/bin/qemu-img install_name_tool -change /opt/local/lib/libglib-2.0.*.dylib @loader_path/libglib-2.0.0.dylib $(DIBS_COMMON_DIR)/bin/check-gl install_name_tool -change /opt/local/lib/libintl.8.dylib @loader_path/libintl.8.dylib $(DIBS_COMMON_DIR)/bin/check-gl install_name_tool -change /opt/local/lib/gcc47/libgcc_s.1.dylib @loader_path/libgcc_s.1.dylib $(DIBS_COMMON_DIR)/bin/check-gl @@ -279,6 +282,7 @@ ifdef CONFIG_DARWIN install_name_tool -change /opt/local/lib/libz.1.dylib @loader_path/libz.1.dylib $(DIBS_X86_DIR)/bin/emulator-x86 ;\ install_name_tool -change /opt/local/lib/libncurses.5.dylib @loader_path/libncurses.5.dylib $(DIBS_X86_DIR)/bin/emulator-x86 ;\ install_name_tool -change /opt/local/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(DIBS_X86_DIR)/bin/emulator-x86 ;\ + install_name_tool -change /usr/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(DIBS_X86_DIR)/bin/emulator-x86 ;\ ;; \ arm-softmmu) \ ;; \ diff --git a/tizen/src/Makefile.tizen b/tizen/src/Makefile.tizen old mode 100755 new mode 100644 index 0dd0b14b9d..17c766949e --- a/tizen/src/Makefile.tizen +++ b/tizen/src/Makefile.tizen @@ -6,13 +6,13 @@ $(call set-vpath, $(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/tizen/sr QEMU_CFLAGS += -I$(SRC_PATH)/hw -I$(SRC_PATH)/tizen/src QEMU_CFLAGS += -I$(SRC_PATH)/tizen/distrib/libav/$(ARCH)/include -QEMU_CFLAGS += -L$(SRC_PATH)/tizen/distrib/libav/$(ARCH)/lib +LDFLAGS += -L$(SRC_PATH)/tizen/distrib/libav/$(ARCH)/lib QEMU_CFLAGS += $(SDL_CFLAGS) QEMU_CFLAGS += $(GLIB_CFLAGS) ifdef CONFIG_DARWIN QEMU_CFLAGS += -framework Foundation -framework SystemConfiguration QEMU_CFLAGS += -framework Cocoa -framework QTKit -framework CoreVideo -QEMU_CFLAGS += -framework AppKit +QEMU_CFLAGS += -framework AppKit -framework CoreServices endif ifndef CONFIG_DEBUG_EXEC CFLAGS += -g -O2 @@ -130,6 +130,7 @@ obj-y += maru_virtio_keyboard.o obj-y += maru_codec.o obj-y += maru_virtio_esm.o obj-y += maru_virtio_hwkey.o +obj-y += maru_brill_codec.o obj-$(CONFIG_PCI) += maru_camera_common_pci.o obj-$(CONFIG_LINUX) += maru_camera_linux_pci.o @@ -155,9 +156,9 @@ obj-y += guest_server.o #ifndef CONFIG_DARWIN ########################################################### ## opengl library for i386 -obj-$(CONFIG_GL) += virtio-gl.o +obj-$(CONFIG_GL) += virtio-gl.o obj-$(CONFIG_GL) += helper_opengl.o opengl_exec.o mesa_mipmap.o -obj-$(CONFIG_NO_GL) += virtio-gl-stub.o +obj-$(CONFIG_NO_GL) += virtio-gl-stub.o obj-y += gloffscreen_test.o gloffscreen_xcomposite.o gloffscreen_common.o gloffscreen_wgl.o gloffscreen_agl.o ########################################################### #endif diff --git a/tizen/src/Makefile.tizen.arm b/tizen/src/Makefile.tizen.arm old mode 100755 new mode 100644 diff --git a/tizen/src/Makefile.tizen.i386 b/tizen/src/Makefile.tizen.i386 old mode 100755 new mode 100644 diff --git a/tizen/src/debug_ch.c b/tizen/src/debug_ch.c index 1696156a8c..6a851fc7ab 100644 --- a/tizen/src/debug_ch.c +++ b/tizen/src/debug_ch.c @@ -419,41 +419,68 @@ const char *dbg_sprintf( const char *format, ... ) int dbg_log( enum _debug_class cls, struct _debug_channel *channel, const char *format, ... ) { - int ret = 0; - int ret_write = 0; - char buf[2048]; - va_list valist; - int open_flags; - int fd; - - if (!(_dbg_get_channel_flags( channel ) & (1 << cls))) - return -1; + int ret = 0; + int ret_write = 0; + char buf_msg[2048]; + char buf_time[128]; + va_list valist; + int open_flags; + int fd; + +#ifdef _WIN32 + struct tm *ptm; +#else + struct tm tm; +#endif + qemu_timeval tv = { 0, 0 }; + time_t ti; - ret += snprintf(buf, sizeof(buf),"[%s:%s", debug_classes[cls], channel->name); + if (!(_dbg_get_channel_flags( channel ) & (1 << cls))) { + return -1; + } - if (*channel->multiname) - ret += snprintf(buf + ret, sizeof(buf) - ret, ":%s]", channel->multiname); - else - ret += snprintf(buf + ret, sizeof(buf) - ret, "]"); + qemu_gettimeofday(&tv); + ti = tv.tv_sec; - va_start(valist, format); - ret += vsnprintf(buf + ret, sizeof(buf) - ret, format, valist ); - va_end(valist); - - open_flags = O_RDWR | O_APPEND | O_BINARY | O_CREAT ; - fd = qemu_open(log_path, open_flags, 0666); - if(fd < 0) { +#ifdef _WIN32 + ptm = localtime(&ti); + strftime(buf_time, sizeof(buf_time), + "%H:%M:%S", ptm); +#else + localtime_r(&ti, &tm); + strftime(buf_time, sizeof(buf_time), + "%H:%M:%S", &tm); +#endif + + ret += snprintf(buf_msg, sizeof(buf_msg),"%s [%s:%s", + buf_time, debug_classes[cls], channel->name); + + if (*channel->multiname) { + ret += snprintf(buf_msg + ret, sizeof(buf_msg) - ret, ":%s]", channel->multiname); + } else { + ret += snprintf(buf_msg + ret, sizeof(buf_msg) - ret, "]"); + } + + va_start(valist, format); + ret += vsnprintf(buf_msg + ret, sizeof(buf_msg) - ret, format, valist); + va_end(valist); + + open_flags = O_RDWR | O_APPEND | O_BINARY | O_CREAT; + + fd = qemu_open(log_path, open_flags, 0666); + if (fd < 0) { fprintf(stderr, "Can't open logfile: %s\n", log_path); - // commented out for prevent shutdown when log directory is removed on runtime. + /* commented out for prevent shutdown when log directory is removed on runtime. */ //exit(1); } - ret_write = qemu_write_full(fd, buf, ret); + + ret_write = qemu_write_full(fd, buf_msg, ret); if (ret_write != ret) { // TODO: error handling... } close(fd); - return ret; + return ret; } void assert_fail(char *exp, const char *file, int line) diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index c44d999a9f..781015c4f8 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -90,12 +90,12 @@ int is_webcam_enabled; #define LEN_MARU_KERNEL_CMDLINE 512 gchar maru_kernel_cmdline[LEN_MARU_KERNEL_CMDLINE]; -static int _skin_argc; +static int _skin_argc = 0; static char **_skin_argv; -static int _qemu_argc; +static int _qemu_argc = 0; static char **_qemu_argv; -#if defined(CONFIG_LINUX) +#if defined(CONFIG_LINUX) || defined(CONFIG_DARWIN) #include extern int g_shmid; #endif @@ -115,8 +115,7 @@ void exit_emulator(void) shutdown_skin_server(); shutdown_guest_server(); -#if defined(CONFIG_LINUX) - /* clean up the vm lock memory by munkyu */ +#if defined(CONFIG_LINUX) || defined(CONFIG_DARWIN) if (shmctl(g_shmid, IPC_RMID, 0) == -1) { ERR("shmctl failed\n"); perror("emulator.c: "); @@ -152,8 +151,9 @@ static void parse_options(int argc, char *argv[], int *skin_argc, int skin_args_index = 0; if (argc <= 1) { - fprintf(stderr, "Arguments are not enough to launch Emulator. " - "Please try to use Emulator Manager.\n"); + fprintf(stderr, + "The arguments are not enough to launch emulator. " + "Please use Emulator Manager.\n"); exit(1); } @@ -362,7 +362,6 @@ static void prepare_basic_features(void) g_strlcpy(dns, DEFAULT_QEMU_DNS_IP, strlen(DEFAULT_QEMU_DNS_IP) + 1); check_vm_lock(); - socket_init(); make_vm_lock(); sdb_setup(); /* determine the base port for emulator */ @@ -510,6 +509,14 @@ static int emulator_main(int argc, char *argv[]) { parse_options(argc, argv, &_skin_argc, &_skin_argv, &_qemu_argc, &_qemu_argv); + + if (_skin_argc <= 0 || _qemu_argc <= 0) { + fprintf(stderr, + "The arguments are not enough to launch emulator. " + "Please use Emulator Manager.\n"); + exit(1); + } + set_bin_path(_qemu_argv[0]); extract_qemu_info(_qemu_argc, _qemu_argv); @@ -537,6 +544,8 @@ static int emulator_main(int argc, char *argv[]) fprintf(stdout, "%s ", _skin_argv[i]); } fprintf(stdout, "\nskin args: =========================================\n"); + INFO("socket initialize\n"); + socket_init(); INFO("qemu main start!\n"); qemu_main(_qemu_argc, _qemu_argv, NULL); diff --git a/tizen/src/guest_server.c b/tizen/src/guest_server.c index 5ca7499ae2..6eea878834 100644 --- a/tizen/src/guest_server.c +++ b/tizen/src/guest_server.c @@ -1,5 +1,5 @@ /* - * + * * * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. * @@ -45,15 +45,16 @@ #include #endif +#include "emulator.h" #include "guest_server.h" #include "mloop_event.h" #include "skin/maruskin_server.h" #include "debug_ch.h" #include "sdb.h" +#include "maru_common.h" MULTI_DEBUG_CHANNEL(qemu, guest_server); - #define RECV_BUF_SIZE 32 static void* run_guest_server(void* args); @@ -63,7 +64,6 @@ static int server_sock = 0; static int parse_val(char *buff, unsigned char data, char *parsbuf); - pthread_t start_guest_server(int server_port) { svr_port = server_port; @@ -80,51 +80,186 @@ pthread_t start_guest_server(int server_port) } -/* get_emulator_vms_sdcard_path = "/home/{USER}/tizen-sdk-data/emulator-vms/sdcard" */ -static char* get_emulator_vms_sdcard_path(void) +/* + * In case that SDK does not refer to sdk.info to get tizen-sdk-data path. + * When SDK is not installed by the latest SDK installer, + * SDK installed path is fixed and there is no sdk.info file. + */ +static gchar *get_old_tizen_sdk_data_path(void) { - char *emulator_vms_sdcard_path = NULL; + gchar *tizen_sdk_data_path = NULL; + + INFO("try to search tizen-sdk-data path in another way.\n"); -#ifndef _WIN32 - char emulator_vms[] = "/tizen-sdk-data/emulator-vms/sdcard/"; - char *homedir = (char*)g_getenv("HOME"); +#ifndef CONFIG_WIN32 + gchar tizen_sdk_data[] = "/tizen-sdk-data"; + gint tizen_sdk_data_len = 0; + gchar *home_dir; - if (!homedir) { - homedir = (char*)g_get_home_dir(); + home_dir = (gchar *)g_getenv("HOME"); + if (!home_dir) { + home_dir = (gchar *)g_get_home_dir(); + } + + tizen_sdk_data_len = strlen(home_dir) + sizeof(tizen_sdk_data) + 1; + tizen_sdk_data_path = g_malloc(tizen_sdk_data_len); + if (!tizen_sdk_data_path) { + ERR("failed to allocate memory.\n"); + return NULL; } + g_strlcpy(tizen_sdk_data_path, home_dir, tizen_sdk_data_len); + g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len); - emulator_vms_sdcard_path = malloc(strlen(homedir) + sizeof emulator_vms + 1); - assert(emulator_vms_sdcard_path != NULL); - strcpy(emulator_vms_sdcard_path, homedir); - strcat(emulator_vms_sdcard_path, emulator_vms); #else - char emulator_vms[] = "\\tizen-sdk-data\\emulator-vms\\sdcard\\"; + gchar tizen_sdk_data[] = "\\tizen-sdk-data\\"; + gint tizen_sdk_data_len = 0; HKEY hKey; char strLocalAppDataPath[1024] = { 0 }; DWORD dwBufLen = 1024; + RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_QUERY_VALUE, &hKey); - RegQueryValueEx(hKey, "Local AppData", NULL, NULL, (LPBYTE)strLocalAppDataPath, &dwBufLen); + RegQueryValueEx(hKey, "Local AppData", NULL, + NULL, (LPBYTE)strLocalAppDataPath, &dwBufLen); RegCloseKey(hKey); - emulator_vms_sdcard_path = malloc(strlen(strLocalAppDataPath) + sizeof emulator_vms + 1); - strcpy(emulator_vms_sdcard_path, strLocalAppDataPath); - strcat(emulator_vms_sdcard_path, emulator_vms); + tizen_sdk_data_len = strlen(strLocalAppDataPath) + sizeof(tizen_sdk_data) + 1; + tizen_sdk_data_path = g_malloc(tizen_sdk_data_len); + if (!tizen_sdk_data_path) { + ERR("failed to allocate memory.\n"); + return NULL; + } + + g_strlcpy(tizen_sdk_data_path, strLocalAppDataPath, tizen_sdk_data_len); + g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len); +#endif + + INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path); + return tizen_sdk_data_path; +} + +/* + * get tizen-sdk-data path from sdk.info. + */ +static gchar *get_tizen_sdk_data_path(void) +{ + gchar *emul_bin_path = NULL; + gchar *sdk_info_file_path = NULL; + gchar *tizen_sdk_data_path = NULL; +#ifndef CONFIG_WIN32 + const char *sdk_info = "../../../sdk.info"; +#else + const char *sdk_info = "..\\..\\..\\sdk.info"; +#endif + const char sdk_data_var[] = "TIZEN_SDK_DATA_PATH"; + + FILE *sdk_info_fp = NULL; + int sdk_info_path_len = 0; + + TRACE("%s\n", __func__); + + emul_bin_path = get_bin_path(); + if (!emul_bin_path) { + ERR("failed to get emulator path.\n"); + return NULL; + } + + sdk_info_path_len = strlen(emul_bin_path) + strlen(sdk_info) + 1; + sdk_info_file_path = g_malloc(sdk_info_path_len); + if (!sdk_info_file_path) { + ERR("failed to allocate sdk-data buffer.\n"); + return NULL; + } + + g_snprintf(sdk_info_file_path, sdk_info_path_len, "%s%s", + emul_bin_path, sdk_info); + INFO("sdk.info path: %s\n", sdk_info_file_path); + + sdk_info_fp = fopen(sdk_info_file_path, "r"); + g_free(sdk_info_file_path); + + if (sdk_info_fp) { + INFO("Succeeded to open [sdk.info].\n"); + + char tmp[256] = { '\0', }; + char *tmpline = NULL; + while (fgets(tmp, sizeof(tmp), sdk_info_fp) != NULL) { + if ((tmpline = g_strstr_len(tmp, sizeof(tmp), sdk_data_var))) { + tmpline += strlen(sdk_data_var) + 1; // 1 for '=' + break; + } + } + + if (tmpline) { + if (tmpline[strlen(tmpline) - 1] == '\n') { + tmpline[strlen(tmpline) - 1] = '\0'; + } + if (tmpline[strlen(tmpline) - 1] == '\r') { + tmpline[strlen(tmpline) - 1] = '\0'; + } + + tizen_sdk_data_path = g_malloc(strlen(tmpline) + 1); + g_strlcpy(tizen_sdk_data_path, tmpline, strlen(tmpline) + 1); + + INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path); + + return tizen_sdk_data_path; + } + + fclose(sdk_info_fp); + } + + // legacy mode + ERR("Failed to open [sdk.info].\n"); + + return get_old_tizen_sdk_data_path(); +} + +static char* get_emulator_vms_sdcard_path(void) +{ + gchar *emulator_vms_sdcard_path = NULL; + gchar *tizen_sdk_data = NULL; +#ifndef CONFIG_WIN32 + char emulator_vms[] = "/emulator-vms/sdcard/"; +#else + char emulator_vms[] = "\\emulator-vms\\sdcard\\"; #endif + TRACE("vms path: %s, %d\n", emulator_vms, sizeof(emulator_vms)); + + tizen_sdk_data = get_tizen_sdk_data_path(); + if (!tizen_sdk_data) { + ERR("failed to get tizen-sdk-data path.\n"); + return NULL; + } + + emulator_vms_sdcard_path = + g_malloc(strlen(tizen_sdk_data) + sizeof(emulator_vms) + 1); + if (!emulator_vms_sdcard_path) { + ERR("failed to allocate memory.\n"); + return NULL; + } + + g_snprintf(emulator_vms_sdcard_path, strlen(tizen_sdk_data) + sizeof(emulator_vms), + "%s%s", tizen_sdk_data, emulator_vms); + + g_free(tizen_sdk_data); + + TRACE("sdcard dir: %s\n", emulator_vms_sdcard_path); return emulator_vms_sdcard_path; } static void* run_guest_server(void* args) { - INFO("start guest server thread.\n"); - - uint16_t port; + uint16_t port = svr_port; + int opt = 1, read_cnt = 0; + char readbuf[RECV_BUF_SIZE]; struct sockaddr_in server_addr, client_addr; socklen_t client_len; - port = svr_port; + + INFO("start guest server thread.\n"); if ((server_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { ERR("create listen socket error\n"); @@ -147,12 +282,11 @@ static void* run_guest_server(void* args) server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); server_addr.sin_port = htons(port); - int opt = 1; - setsockopt( server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof( opt ) ); + setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - if ( 0 > bind( server_sock, (struct sockaddr*) &server_addr, sizeof( server_addr ) ) ) { - ERR( "guest server bind error: " ); - perror( "bind" ); + if (bind(server_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) { + ERR("guest server bind error: "); + perror("bind"); #ifdef _WIN32 if (server_sock) { closesocket(server_sock); @@ -165,32 +299,29 @@ static void* run_guest_server(void* args) server_sock = 0; return NULL; } else { - INFO( "success to bind port[127.0.0.1:%d/udp] for guest_server in host \n", port ); + INFO("success to bind port[127.0.0.1:%d/udp] for guest_server in host \n", port); } - client_len = sizeof( client_addr ); - - char readbuf[RECV_BUF_SIZE]; + client_len = sizeof(client_addr); + INFO("guest server start...port:%d\n", port); - INFO( "guest server start...port:%d\n", port ); - - while ( 1 ) { + while (1) { memset(&readbuf, 0, RECV_BUF_SIZE); if (server_sock == 0) { INFO("server_sock is closed\n"); return NULL; } - int read_cnt = recvfrom(server_sock, readbuf, - RECV_BUF_SIZE, 0, (struct sockaddr*) &client_addr, &client_len); + read_cnt = recvfrom(server_sock, readbuf, RECV_BUF_SIZE, 0, + (struct sockaddr*) &client_addr, &client_len); - if (0 > read_cnt) { + if (read_cnt < 0) { ERR("fail to recvfrom in guest_server.\n"); perror("fail to recvfrom in guest_server.:"); break; } else { - if (0 == read_cnt) { + if (read_cnt == 0) { ERR("read_cnt is 0.\n"); break; } @@ -208,12 +339,11 @@ static void* run_guest_server(void* args) if (strcmp(command, "2\n" ) == 0) { TRACE("command:%s\n", command); notify_sdb_daemon_start(); - } - if (strcmp(command, "3\n" ) == 0) { + } else if (strcmp(command, "3\n" ) == 0) { TRACE("command:%s\n", command); notify_sensor_daemon_start(); - } - else if (strcmp(command, "4\n") == 0) { + notify_sdb_daemon_start(); + } else if (strcmp(command, "4\n") == 0) { /* sdcard mount/umount msg recv from emuld */ INFO("command:%s\n", command); char token[] = "\n"; @@ -231,20 +361,25 @@ static void* run_guest_server(void* args) } else if (atoi(ret) == 1) { /* mount sdcard */ char sdcard_path[256]; - char* vms_path = get_emulator_vms_sdcard_path(); - memset(sdcard_path, '\0', sizeof(sdcard_path)); + char* vms_path = NULL; - strcpy(sdcard_path, vms_path); + vms_path = get_emulator_vms_sdcard_path(); + if (vms_path) { + g_strlcpy(sdcard_path, vms_path, sizeof(sdcard_path)); - /* emulator_vms_sdcard_path + sdcard img name */ - ret = strtok(NULL, token); - strcat(sdcard_path, ret); - INFO("%s\n", sdcard_path); + /* emulator_vms_sdcard_path + sdcard img name */ + ret = strtok(NULL, token); - //mloop_evcmd_usbdisk(sdcard_path); - mloop_evcmd_sdcard(sdcard_path); + g_strlcat(sdcard_path, ret, sizeof(sdcard_path)); + TRACE("sdcard path: %s\n", sdcard_path); - free(vms_path); + //mloop_evcmd_usbdisk(sdcard_path); + mloop_evcmd_sdcard(sdcard_path); + + g_free(vms_path); + } else { + ERR("failed to get sdcard path!!\n"); + } } else { ERR("!!! unknown command : %s\n", ret); } @@ -256,7 +391,7 @@ static void* run_guest_server(void* args) } } -#ifdef _WIN32 +#ifdef CONFIG_WIN32 if (server_sock) { closesocket(server_sock); } @@ -266,6 +401,7 @@ static void* run_guest_server(void* args) } #endif server_sock = 0; + return NULL; } @@ -273,7 +409,7 @@ static int parse_val(char* buff, unsigned char data, char* parsbuf) { int count = 0; - while ( 1 ) { + while (1) { if (count > 12) { return -1; } @@ -306,4 +442,3 @@ void shutdown_guest_server(void) server_sock = 0; } - diff --git a/tizen/src/hw/gloffscreen.h b/tizen/src/hw/gloffscreen.h index f317619baa..e21b0db862 100644 --- a/tizen/src/hw/gloffscreen.h +++ b/tizen/src/hw/gloffscreen.h @@ -75,41 +75,46 @@ extern const char *glo_glXQueryExtensionsString(void); extern GloContext *__glo_context_create(int formatFlags); /* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */ -extern GloContext *glo_context_create(int formatFlags, GloContext *shareLists); +extern GloContext *glo_context_create(int formatFlags, GloContext * shareLists); /* Destroy a previouslu created OpenGL context */ -extern void glo_context_destroy(GloContext *context); +extern void glo_context_destroy(GloContext * context); /* Update the context in surface and free previous light-weight context */ -extern void glo_surface_update_context(GloSurface *surface, GloContext *context, int free_flags); +extern void glo_surface_update_context(GloSurface * surface, + GloContext * context, int free_flags); /* Link the pixmap/pbuffer associated with surface as texture. * ctxt is the target context for the texture operation */ -extern void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface, int surface_type); +extern void glo_surface_as_texture(GloContext * ctxt, GloSurface * surface, + int surface_type); /* Create a surface with given width and height, */ -extern GloSurface *glo_surface_create(int width, int height, GloContext *context); +extern GloSurface *glo_surface_create(int width, int height, + GloContext * context); /* Destroy the given surface */ -extern void glo_surface_destroy(GloSurface *surface); +extern void glo_surface_destroy(GloSurface * surface); /* Make the given surface current */ -extern int glo_surface_makecurrent(GloSurface *surface); +extern int glo_surface_makecurrent(GloSurface * surface); /* Get the contents of the given surface. Note that this is top-down, not * bottom-up as glReadPixels would do. */ -extern void glo_surface_getcontents(GloSurface *surface, int stride, int type, void *data); +extern void glo_surface_getcontents(GloSurface * surface, int stride, int type, + void *data); /* Return the width and height of the given surface */ -extern void glo_surface_get_size(GloSurface *surface, int *width, int *height); +extern void glo_surface_get_size(GloSurface * surface, int *width, int *height); /* Functions to decode the format flags */ extern int glo_flags_get_depth_bits(int formatFlags); extern int glo_flags_get_stencil_bits(int formatFlags); extern void glo_flags_get_rgba_bits(int formatFlags, int *rgba); extern int glo_flags_get_bytes_per_pixel(int formatFlags); -extern void glo_flags_get_readpixel_type(int formatFlags, int *glFormat, int *glType); +extern void glo_flags_get_readpixel_type(int formatFlags, int *glFormat, + int *glType); /* Score how close the given format flags match. 0=great, >0 not so great */ extern int glo_flags_score(int formatFlagsExpected, int formatFlagsReal); @@ -123,7 +128,11 @@ extern int glo_flags_get_from_glx(const int *fbConfig, int assumeBooleans); extern int glo_get_glx_from_flags(int formatFlags, int glxEnum); /* Get the width and height from attrib_list */ -extern void glo_geometry_get_from_glx(const int* attrib_list, int* width, int* height); +extern void glo_geometry_get_from_glx(const int *attrib_list, int *width, + int *height); + +extern void glo_surface_release_texture(GloSurface * surface); +extern void glo_surface_updatecontents(GloSurface * surface); /* In terms of speed, glReadPixels actually seems the best we can do. * * On Windows PFB_DRAW_TO_BITMAP is software-only. @@ -136,4 +145,4 @@ extern void glo_geometry_get_from_glx(const int* attrib_list, int* width, int* h * doing this on Windows at least. */ -#endif /* GLOFFSCREEN_H_ */ +#endif /* GLOFFSCREEN_H_ */ diff --git a/tizen/src/hw/gloffscreen_agl.c b/tizen/src/hw/gloffscreen_agl.c index 5ae68c58fd..d20aff0bbc 100644 --- a/tizen/src/hw/gloffscreen_agl.c +++ b/tizen/src/hw/gloffscreen_agl.c @@ -19,106 +19,100 @@ * 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. -*/ -#ifdef __APPLE__ - -#include -#include -#include +*/ +#ifdef __APPLE__ + +#include +#include +#include #include #include /*hack due to conflicting typedefs in qemu's softfloat.h*/ #define __SECURITYHI__ 1 - -#include -#include -#include "gloffscreen.h" - -#ifdef GL_DEBUG -#define TRACE(fmt, ...) printf("%s@%d: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) -#else -#define TRACE(...) -#endif - -struct _GloContext -{ - GLuint formatFlags; - AGLPixelFormat pixelFormat; - AGLContext context; - }; - -struct _GloSurface -{ - GLuint width; - GLuint height; - GloContext *context; - AGLPbuffer pbuffer; - }; - -extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, - int bpp, int width, int height, - void *data, int noflip); - - - -/* Initialise gloffscreen */ -int glo_init(void) + +#include +#include +#include "gloffscreen.h" + +#ifdef GL_DEBUG +#define TRACE(fmt, ...) printf("%s@%d: " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define TRACE(...) +#endif + +struct _GloContext { + GLuint formatFlags; + AGLPixelFormat pixelFormat; + AGLContext context; +}; + +struct _GloSurface { + GLuint width; + GLuint height; + GloContext *context; + AGLPbuffer pbuffer; +}; + +extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, + int bpp, int width, int height, + void *data, int noflip); + +/* Initialise gloffscreen */ +int glo_init(void) +{ + int major, minor; + aglGetVersion(&major, &minor); + fprintf(stdout, "%s----AGL version %d.%d\n", __FUNCTION__, major, minor); + return 0; +} + +/* Uninitialise gloffscreen */ +void glo_kill(void) +{ + +} + +const char *glo_glXQueryExtensionsString(void) +{ + return ""; +} + +/* Like wglGetProcAddress/glxGetProcAddress */ +void *glo_getprocaddress(const char *procName) { - int major, minor; - aglGetVersion(&major, &minor); - fprintf(stdout, "%s----AGL version %d.%d\n",__FUNCTION__, major, minor); - return 0; - } - -/* Uninitialise gloffscreen */ -void glo_kill(void) -{ - -} - -const char *glo_glXQueryExtensionsString(void) -{ - return ""; - } - -/* Like wglGetProcAddress/glxGetProcAddress */ - void *glo_getprocaddress(const char *procName) - { void *ret = NULL; - if (procName) - { - if (!strncmp(procName, "glX", 3)) - ret = (void *)1; - else + if (procName) { + if (!strncmp(procName, "glX", 3)) + ret = (void *)1; + else ret = dlsym(RTLD_NEXT, procName); - } - -#if 0//standard code for mac to look up procaddress, but seems slow that above. - NSSymbol symbol; - char *symbolname; - symbolname = malloc(strlen(procName) +2); - strcpy(symbolname +1, procName); - symbolname[0] = '_'; - symbol = NULL; - if(NSIsSymbolNameDefined(symbolname)) - symbol = NSLookupAndBindSymbol(symbolname); - free(symbolname); - ret = symbol ? NSAddressOfSymbol (symbol) : NULL; -#endif - TRACE("'%s' --> %p", procName, ret); - return ret; -} - + } +#if 0 //standard code for mac to look up procaddress, but seems slow that above. + NSSymbol symbol; + char *symbolname; + symbolname = malloc(strlen(procName) + 2); + strcpy(symbolname + 1, procName); + symbolname[0] = '_'; + symbol = NULL; + if (NSIsSymbolNameDefined(symbolname)) + symbol = NSLookupAndBindSymbol(symbolname); + free(symbolname); + ret = symbol ? NSAddressOfSymbol(symbol) : NULL; +#endif + TRACE("'%s' --> %p", procName, ret); + return ret; +} + /* Create an OpenGL context for a certain pixel format. * formatflags are from the GLO_ constants */ GloContext *__glo_context_create(int formatFlags) { - int rgba[4]; - glo_flags_get_rgba_bits(formatFlags, rgba); - const int attribs[] = { + int rgba[4]; + glo_flags_get_rgba_bits(formatFlags, rgba); + const int attribs[] = { AGL_RGBA, AGL_MINIMUM_POLICY, AGL_PIXEL_SIZE, glo_flags_get_bytes_per_pixel(formatFlags) * 8, @@ -139,45 +133,67 @@ GloContext *__glo_context_create(int formatFlags) glo_flags_get_depth_bits(formatFlags), glo_flags_get_stencil_bits(formatFlags)); - AGLPixelFormat pf = aglChoosePixelFormat(NULL, 0, attribs); + AGLPixelFormat pf = aglChoosePixelFormat(NULL, 0, attribs); if (pf == NULL) fprintf(stderr, "No matching pixelformat found."); - else - { + else { GLint bpp = 0, a = 0, d = 0, s = 0; aglDescribePixelFormat(pf, AGL_PIXEL_SIZE, &bpp); aglDescribePixelFormat(pf, AGL_ALPHA_SIZE, &a); aglDescribePixelFormat(pf, AGL_DEPTH_SIZE, &d); aglDescribePixelFormat(pf, AGL_STENCIL_SIZE, &s); - formatFlags &= ~(GLO_FF_ALPHA_MASK | GLO_FF_BITS_MASK | GLO_FF_DEPTH_MASK | GLO_FF_STENCIL_MASK); + formatFlags &= + ~(GLO_FF_ALPHA_MASK | GLO_FF_BITS_MASK | GLO_FF_DEPTH_MASK | + GLO_FF_STENCIL_MASK); switch (bpp) { - case 16: formatFlags |= GLO_FF_BITS_16; break; - case 24: formatFlags |= GLO_FF_BITS_24; break; - case 32: formatFlags |= GLO_FF_BITS_32; break; - default: fprintf(stderr, "got unsupported bpp %d", bpp); break; - } - - if (a > 0) - { + case 16: + formatFlags |= GLO_FF_BITS_16; + break; + case 24: + formatFlags |= GLO_FF_BITS_24; + break; + case 32: + formatFlags |= GLO_FF_BITS_32; + break; + default: + fprintf(stderr, "got unsupported bpp %d", bpp); + break; + } + + if (a > 0) { formatFlags |= GLO_FF_ALPHA; } switch (d) { - case 0: break; - case 16: formatFlags |= GLO_FF_DEPTH_16; break; - case 24: formatFlags |= GLO_FF_DEPTH_24; break; - case 32: formatFlags |= GLO_FF_DEPTH_32; break; - default: fprintf(stderr, "got unsupported depth %d", d); break; + case 0: + break; + case 16: + formatFlags |= GLO_FF_DEPTH_16; + break; + case 24: + formatFlags |= GLO_FF_DEPTH_24; + break; + case 32: + formatFlags |= GLO_FF_DEPTH_32; + break; + default: + fprintf(stderr, "got unsupported depth %d", d); + break; } switch (s) { - case 0: break; - case 8: formatFlags |= GLO_FF_STENCIL_8; break; - default: fprintf(stderr, "got unsupported stencil %d", s); break; - } - } - GloContext *context = (GloContext *)g_malloc(sizeof(*context)); + case 0: + break; + case 8: + formatFlags |= GLO_FF_STENCIL_8; + break; + default: + fprintf(stderr, "got unsupported stencil %d", s); + break; + } + } + GloContext *context = (GloContext *) g_malloc(sizeof(*context)); memset(context, 0, sizeof(*context)); context->formatFlags = formatFlags; context->pixelFormat = pf; @@ -185,180 +201,183 @@ GloContext *__glo_context_create(int formatFlags) return context; } - -GloContext *glo_context_create(int formatFlags, GloContext *shareLists) -{ - GloContext *context = __glo_context_create(formatFlags); - if(!context) - return NULL; - - context->context = aglCreateContext(context->pixelFormat, shareLists ? shareLists->context : NULL); - if (context->context == NULL) - { - fprintf(stderr, "aglCreateContext failed: %s", aglErrorString(aglGetError())); - } - - else - { - if(context->pixelFormat != NULL) - { - aglDestroyPixelFormat(context->pixelFormat); - context->pixelFormat = NULL; - } - } - - TRACE("context=%p", context); - return context; -} - -/* Destroy a previously created OpenGL context */ -void glo_context_destroy(GloContext *context) -{ - TRACE("context=%p", context); - if (context) - { - aglDestroyContext(context->context); - if(context->pixelFormat != NULL) - { - aglDestroyPixelFormat(context->pixelFormat); - context->pixelFormat = NULL; - } - context->context = NULL; - g_free(context); - } + +GloContext *glo_context_create(int formatFlags, GloContext * shareLists) +{ + GloContext *context = __glo_context_create(formatFlags); + if (!context) + return NULL; + + context->context = + aglCreateContext(context->pixelFormat, + shareLists ? shareLists->context : NULL); + if (context->context == NULL) { + fprintf(stderr, "aglCreateContext failed: %s", + aglErrorString(aglGetError())); + } + + else { + if (context->pixelFormat != NULL) { + aglDestroyPixelFormat(context->pixelFormat); + context->pixelFormat = NULL; + } + } + + TRACE("context=%p", context); + return context; +} + +/* Destroy a previously created OpenGL context */ +void glo_context_destroy(GloContext * context) +{ + TRACE("context=%p", context); + if (context) { + aglDestroyContext(context->context); + if (context->pixelFormat != NULL) { + aglDestroyPixelFormat(context->pixelFormat); + context->pixelFormat = NULL; + } + context->context = NULL; + g_free(context); + } } -void glo_surface_update_context(GloSurface *surface, GloContext *context, int free_flags) +void glo_surface_update_context(GloSurface * surface, GloContext * context, + int free_flags) { - if ( surface->context ) - { - if ( free_flags) /* light-weight context */ + if (surface->context) { + if (free_flags) /* light-weight context */ g_free(surface->context); } surface->context = context; } - - /* Create a surface with given width and height, formatflags are from the - * GLO_ constants */ -GloSurface *glo_surface_create(int width, int height, GloContext *context) -{ - GloSurface *surface = NULL; - if (context) - { - surface = (GloSurface *)g_malloc(sizeof(*surface)); - memset(surface, 0, sizeof(*surface)); - surface->width = width; - surface->height = height; - surface->context = context; - - TRACE("%dx%d", surface->width, surface->height); - if (aglCreatePBuffer(width, height, GL_TEXTURE_2D, GL_RGBA, 0, &surface->pbuffer) == GL_FALSE) - fprintf(stderr, "aglCreatePbuffer failed: %s", aglErrorString(aglGetError())); - - } - TRACE("surface=%p", surface); - return surface; -} - -/* Destroy the given surface */ -void glo_surface_destroy(GloSurface *surface) -{ - TRACE("surface=%p", surface); - if (surface) - { - aglDestroyPBuffer(surface->pbuffer); - surface->pbuffer = NULL; - g_free(surface); - } -} - -/* Make the given surface current */ -int glo_surface_makecurrent(GloSurface *surface) -{ - int ret = GL_FALSE; - TRACE("surface=%p", surface); - if (surface) - { - if (aglSetPBuffer(surface->context->context, surface->pbuffer, 0, 0, 0) == GL_FALSE) - fprintf(stderr, "aglSetPbuffer failed: %s", aglErrorString(aglGetError())); - ret = aglSetCurrentContext(surface->context->context); - } else - { - ret = aglSetCurrentContext(NULL); - } + * GLO_ constants */ +GloSurface *glo_surface_create(int width, int height, GloContext * context) +{ + GloSurface *surface = NULL; + if (context) { + surface = (GloSurface *) g_malloc(sizeof(*surface)); + memset(surface, 0, sizeof(*surface)); + surface->width = width; + surface->height = height; + surface->context = context; + + TRACE("%dx%d", surface->width, surface->height); + if (aglCreatePBuffer + (width, height, GL_TEXTURE_2D, GL_RGBA, 0, + &surface->pbuffer) == GL_FALSE) + fprintf(stderr, "aglCreatePbuffer failed: %s", + aglErrorString(aglGetError())); + + } + TRACE("surface=%p", surface); + return surface; +} + +/* Destroy the given surface */ +void glo_surface_destroy(GloSurface * surface) +{ + TRACE("surface=%p", surface); + if (surface) { + aglDestroyPBuffer(surface->pbuffer); + surface->pbuffer = NULL; + g_free(surface); + } +} + +/* Make the given surface current */ +int glo_surface_makecurrent(GloSurface * surface) +{ + int ret = GL_FALSE; + TRACE("surface=%p", surface); + if (surface) { + if (aglSetPBuffer(surface->context->context, surface->pbuffer, 0, 0, 0) + == GL_FALSE) + fprintf(stderr, "aglSetPbuffer failed: %s", + aglErrorString(aglGetError())); + ret = aglSetCurrentContext(surface->context->context); + } else { + ret = aglSetCurrentContext(NULL); + } if (ret == GL_FALSE) - fprintf(stderr, "aglSetCurrentContext failed: %s", aglErrorString(aglGetError())); - - TRACE("Return ret=%d\n", ret); - return ret; - } + fprintf(stderr, "aglSetCurrentContext failed: %s", + aglErrorString(aglGetError())); -void glo_surface_updatecontents(GloSurface *surface) + TRACE("Return ret=%d\n", ret); + return ret; +} + +void glo_surface_updatecontents(GloSurface * surface) { - const GLint swap_interval = 1; + const GLint swap_interval = 1; + + if (!surface) + return; + aglSwapBuffers(surface->context->context); + aglSetInteger(surface->context->context, AGL_SWAP_INTERVAL, &swap_interval); +} - if(!surface) - return; - aglSwapBuffers(surface->context->context); - aglSetInteger(surface->context->context, AGL_SWAP_INTERVAL, &swap_interval); +/* Get the contents of the given surface */ +void glo_surface_getcontents(GloSurface * surface, int stride, int bpp, + void *data) +{ + const GLint swap_interval = 1; + if (surface) { + aglSwapBuffers(surface->context->context); + aglSetInteger(surface->context->context, AGL_SWAP_INTERVAL, + &swap_interval); + glo_surface_getcontents_readpixels(surface->context->formatFlags, + stride, bpp, surface->width, + surface->height, data, 0); + } } - -/* Get the contents of the given surface */ -void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, - void *data) +/* Return the width and height of the given surface */ +void glo_surface_get_size(GloSurface * surface, int *width, int *height) { - const GLint swap_interval = 1; - if (surface) - { - aglSwapBuffers(surface->context->context); - aglSetInteger(surface->context->context, AGL_SWAP_INTERVAL, &swap_interval); - glo_surface_getcontents_readpixels(surface->context->formatFlags, stride, bpp, surface->width, surface->height, data, 0); - } -} - -/* Return the width and height of the given surface */ -void glo_surface_get_size(GloSurface *surface, int *width, int *height) -{ - if (width) - { - *width = surface->width; - } - - if (height) - { - *height = surface->height; - } -} - + if (width) { + *width = surface->width; + } + + if (height) { + *height = surface->height; + } +} + /* Bind the surface as texture */ -void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface, int surface_type) +void glo_surface_as_texture(GloContext * ctxt, GloSurface * surface, + int surface_type) { #if 0 - //Not QUit sure about this function; - int glFormat, glType; - glo_surface_updatecontents(surface); - /*XXX: changet the fixed target: GL_TEXTURE_2D*/ - glo_flags_get_readpixel_type(surface->context->formatFlags, &glFormat, &glType); - fprintf(stderr, "surface_as_texture:teximage:width=%d,height=%d, glFormat=0x%x, glType=0x%x.\n", surface->width, surface->height, glFormat, glType); + //Not QUit sure about this function; + int glFormat, glType; + glo_surface_updatecontents(surface); + /*XXX: changet the fixed target: GL_TEXTURE_2D */ + glo_flags_get_readpixel_type(surface->context->formatFlags, &glFormat, + &glType); + fprintf(stderr, + "surface_as_texture:teximage:width=%d,height=%d, glFormat=0x%x, glType=0x%x.\n", + surface->width, surface->height, glFormat, glType); /* glTexImage2D use different RGB order than the contexts in the pixmap surface */ /* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->image->data);*/ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, glFormat, glType, surface->pbuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, + glFormat, glType, surface->pbuffer); #else - if (aglTexImagePBuffer(ctxt->context, surface->pbuffer, GL_BACK) == GL_FALSE) - fprintf(stderr, "aglTexImagePBuffer failed: %s", aglErrorString(aglGetError())); + if (aglTexImagePBuffer(ctxt->context, surface->pbuffer, GL_BACK) == + GL_FALSE) + fprintf(stderr, "aglTexImagePBuffer failed: %s", + aglErrorString(aglGetError())); - glFinish(); + glFinish(); #endif } -void glo_surface_release_texture(GloSurface *surface) +void glo_surface_release_texture(GloSurface * surface) { } - -#endif +#endif diff --git a/tizen/src/hw/gloffscreen_common.c b/tizen/src/hw/gloffscreen_common.c index c8fd382c9b..188fc98222 100644 --- a/tizen/src/hw/gloffscreen_common.c +++ b/tizen/src/hw/gloffscreen_common.c @@ -30,7 +30,7 @@ #include #include #include -#elif __APPLE__ +#elif defined __APPLE__ #include #else #include @@ -102,94 +102,110 @@ void g_free(void *ptr); // --------------------------------------------------- extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, - int bpp, int width, int height, void *data, int noflip); + int bpp, int width, int height, + void *data, int noflip); // --------------------------------------------------- -int glo_flags_get_depth_bits(int formatFlags) { - switch ( formatFlags & GLO_FF_DEPTH_MASK ) { - case GLO_FF_DEPTH_16: return 16; - case GLO_FF_DEPTH_24: return 24; - case GLO_FF_DEPTH_32: return 32; - default: return 0; +int glo_flags_get_depth_bits(int formatFlags) +{ + switch (formatFlags & GLO_FF_DEPTH_MASK) { + case GLO_FF_DEPTH_16: + return 16; + case GLO_FF_DEPTH_24: + return 24; + case GLO_FF_DEPTH_32: + return 32; + default: + return 0; } } -int glo_flags_get_stencil_bits(int formatFlags) { - switch ( formatFlags & GLO_FF_STENCIL_MASK ) { - case GLO_FF_STENCIL_8: return 8; - default: return 0; +int glo_flags_get_stencil_bits(int formatFlags) +{ + switch (formatFlags & GLO_FF_STENCIL_MASK) { + case GLO_FF_STENCIL_8: + return 8; + default: + return 0; } } -void glo_flags_get_rgba_bits(int formatFlags, int *rgba) { +void glo_flags_get_rgba_bits(int formatFlags, int *rgba) +{ int alpha = (formatFlags & GLO_FF_ALPHA) != 0; - switch ( formatFlags & GLO_FF_BITS_MASK ) { - case GLO_FF_BITS_16: - rgba[0] = alpha ? 4 : 5; - rgba[1] = alpha ? 4 : 6; - rgba[2] = alpha ? 4 : 5; - rgba[3] = alpha ? 4 : 0; - break; - case GLO_FF_BITS_24: - // ignore alpha - rgba[0] = 8; - rgba[1] = 8; - rgba[2] = 8; - rgba[3] = 0; - break; - case GLO_FF_BITS_32: - rgba[0] = 8; - rgba[1] = 8; - rgba[2] = 8; - rgba[3] = 8; - break; - default: - rgba[0] = 8; - rgba[1] = 8; - rgba[2] = 8; - rgba[3] = 0; - break; - } + switch (formatFlags & GLO_FF_BITS_MASK) { + case GLO_FF_BITS_16: + rgba[0] = alpha ? 4 : 5; + rgba[1] = alpha ? 4 : 6; + rgba[2] = alpha ? 4 : 5; + rgba[3] = alpha ? 4 : 0; + break; + case GLO_FF_BITS_24: + // ignore alpha + rgba[0] = 8; + rgba[1] = 8; + rgba[2] = 8; + rgba[3] = 0; + break; + case GLO_FF_BITS_32: + rgba[0] = 8; + rgba[1] = 8; + rgba[2] = 8; + rgba[3] = 8; + break; + default: + rgba[0] = 8; + rgba[1] = 8; + rgba[2] = 8; + rgba[3] = 0; + break; + } } -int glo_flags_get_bytes_per_pixel(int formatFlags) { - switch ( formatFlags & GLO_FF_BITS_MASK ) { - case GLO_FF_BITS_16: return 2; - case GLO_FF_BITS_24: return 3; - case GLO_FF_BITS_32: return 4; - default: return 3; +int glo_flags_get_bytes_per_pixel(int formatFlags) +{ + switch (formatFlags & GLO_FF_BITS_MASK) { + case GLO_FF_BITS_16: + return 2; + case GLO_FF_BITS_24: + return 3; + case GLO_FF_BITS_32: + return 4; + default: + return 3; } } -void glo_flags_get_readpixel_type(int formatFlags, int *glFormat, int *glType) { +void glo_flags_get_readpixel_type(int formatFlags, int *glFormat, int *glType) +{ GLenum gFormat, gType; if (formatFlags & GLO_FF_ALPHA) { - switch ( formatFlags & GLO_FF_BITS_MASK ) { - case GLO_FF_BITS_16: - gFormat = GL_RGBA; - gType = GL_UNSIGNED_SHORT_4_4_4_4; - break; - case GLO_FF_BITS_24: - case GLO_FF_BITS_32: - default: - gFormat = GL_BGRA; - gType = GL_UNSIGNED_BYTE; - break; + switch (formatFlags & GLO_FF_BITS_MASK) { + case GLO_FF_BITS_16: + gFormat = GL_RGBA; + gType = GL_UNSIGNED_SHORT_4_4_4_4; + break; + case GLO_FF_BITS_24: + case GLO_FF_BITS_32: + default: + gFormat = GL_BGRA; + gType = GL_UNSIGNED_BYTE; + break; } } else { - switch ( formatFlags & GLO_FF_BITS_MASK ) { - case GLO_FF_BITS_16: - gFormat = GL_RGB; - gType = GL_UNSIGNED_SHORT_5_6_5; - break; - case GLO_FF_BITS_24: - case GLO_FF_BITS_32: - default: - gFormat = GL_BGR; - gType = GL_UNSIGNED_BYTE; - break; + switch (formatFlags & GLO_FF_BITS_MASK) { + case GLO_FF_BITS_16: + gFormat = GL_RGB; + gType = GL_UNSIGNED_SHORT_5_6_5; + break; + case GLO_FF_BITS_24: + case GLO_FF_BITS_32: + default: + gFormat = GL_BGR; + gType = GL_UNSIGNED_BYTE; + break; } } @@ -201,7 +217,8 @@ void glo_flags_get_readpixel_type(int formatFlags, int *glFormat, int *glType) { #if 0 // seems wrong below. -int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) { +int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) +{ if (formatFlagsExpected == formatFlagsReal) return 0; @@ -209,26 +226,27 @@ int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) { int score = 1; // we wanted alpha, but we didn't get it - if ((formatFlagsExpected&GLO_FF_ALPHA_MASK) < - (formatFlagsReal&GLO_FF_ALPHA_MASK)) + if ((formatFlagsExpected & GLO_FF_ALPHA_MASK) < + (formatFlagsReal & GLO_FF_ALPHA_MASK)) score++; // less bits than we expected - if ((formatFlagsExpected&GLO_FF_BITS_MASK) < - !(formatFlagsReal&GLO_FF_BITS_MASK)) + if ((formatFlagsExpected & GLO_FF_BITS_MASK) < + !(formatFlagsReal & GLO_FF_BITS_MASK)) score++; // less depth bits than we expected - if ((formatFlagsExpected&GLO_FF_DEPTH_MASK) < - !(formatFlagsReal&GLO_FF_DEPTH_MASK)) + if ((formatFlagsExpected & GLO_FF_DEPTH_MASK) < + !(formatFlagsReal & GLO_FF_DEPTH_MASK)) score++; // less stencil bits than we expected - if ((formatFlagsExpected&GLO_FF_STENCIL_MASK) < - !(formatFlagsReal&GLO_FF_STENCIL_MASK)) + if ((formatFlagsExpected & GLO_FF_STENCIL_MASK) < + !(formatFlagsReal & GLO_FF_STENCIL_MASK)) score++; return score; } #else -int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) { +int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) +{ if (formatFlagsExpected == formatFlagsReal) return 0; @@ -237,7 +255,7 @@ int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) { // we wanted alpha, but we didn't get it if ((formatFlagsReal & GLO_FF_ALPHA_MASK) < - (formatFlagsExpected & GLO_FF_ALPHA_MASK)) + (formatFlagsExpected & GLO_FF_ALPHA_MASK)) score++; // less bits than we expected if ((formatFlagsReal & GLO_FF_BITS_MASK) < @@ -256,144 +274,146 @@ int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) { } #endif -int glo_flags_get_from_glx(const int *fbConfig, int assumeBooleans) { +int glo_flags_get_from_glx(const int *fbConfig, int assumeBooleans) +{ int bufferSize = 0; int depthSize = 0; int stencilSize = 0; - int rgbaSize[] = {0,0,0,0}; + int rgbaSize[] = { 0, 0, 0, 0 }; int flags = 0; while (*fbConfig) { int isSingle = 0; switch (*fbConfig) { - case GLX_USE_GL: - isSingle = 1; - break; - case GLX_BUFFER_SIZE: - bufferSize = fbConfig[1]; - break; - case GLX_LEVEL: - break; - case GLX_RGBA: - flags |= GLO_FF_ALPHA; - break; - case GLX_DOUBLEBUFFER: - isSingle = 1; - break; - case GLX_STEREO: - isSingle = 1; - break; - case GLX_AUX_BUFFERS: - break; - case GLX_RED_SIZE: - rgbaSize[0] = fbConfig[1]; - break; - case GLX_GREEN_SIZE: - rgbaSize[1] = fbConfig[1]; - break; - case GLX_BLUE_SIZE: - rgbaSize[2] = fbConfig[1]; - break; - case GLX_ALPHA_SIZE: - rgbaSize[3] = fbConfig[1]; - break; - case GLX_DEPTH_SIZE: - depthSize = fbConfig[1]; - break; - case GLX_STENCIL_SIZE: - stencilSize = fbConfig[1]; - break; - case GLX_ACCUM_RED_SIZE: - case GLX_ACCUM_GREEN_SIZE: - case GLX_ACCUM_BLUE_SIZE: - case GLX_ACCUM_ALPHA_SIZE: - break; - default: - break; + case GLX_USE_GL: + isSingle = 1; + break; + case GLX_BUFFER_SIZE: + bufferSize = fbConfig[1]; + break; + case GLX_LEVEL: + break; + case GLX_RGBA: + flags |= GLO_FF_ALPHA; + break; + case GLX_DOUBLEBUFFER: + isSingle = 1; + break; + case GLX_STEREO: + isSingle = 1; + break; + case GLX_AUX_BUFFERS: + break; + case GLX_RED_SIZE: + rgbaSize[0] = fbConfig[1]; + break; + case GLX_GREEN_SIZE: + rgbaSize[1] = fbConfig[1]; + break; + case GLX_BLUE_SIZE: + rgbaSize[2] = fbConfig[1]; + break; + case GLX_ALPHA_SIZE: + rgbaSize[3] = fbConfig[1]; + break; + case GLX_DEPTH_SIZE: + depthSize = fbConfig[1]; + break; + case GLX_STENCIL_SIZE: + stencilSize = fbConfig[1]; + break; + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + case GLX_ACCUM_ALPHA_SIZE: + break; + default: + break; } // go to next if (isSingle && assumeBooleans) fbConfig++; else - fbConfig+=2; + fbConfig += 2; } if (rgbaSize[3]) flags |= GLO_FF_ALPHA; // ensure we have room for *some* alpha - if ((flags & GLO_FF_ALPHA) && (rgbaSize[3]==0)) + if ((flags & GLO_FF_ALPHA) && (rgbaSize[3] == 0)) rgbaSize[3] = 1; // Buffer size flag - if (bufferSize==0) - bufferSize = rgbaSize[0]+rgbaSize[1]+rgbaSize[2]+rgbaSize[3]; - if (bufferSize==0) + if (bufferSize == 0) + bufferSize = rgbaSize[0] + rgbaSize[1] + rgbaSize[2] + rgbaSize[3]; + if (bufferSize == 0) bufferSize = (flags & GLO_FF_ALPHA) ? 32 : 24; - if (bufferSize<=16) + if (bufferSize <= 16) flags |= GLO_FF_BITS_16; - else if (bufferSize<=24) + else if (bufferSize <= 24) flags |= GLO_FF_BITS_24; else flags |= GLO_FF_BITS_32; // Depth - if (depthSize<=16) + if (depthSize <= 16) flags |= GLO_FF_DEPTH_16; - else if (depthSize<=24) + else if (depthSize <= 24) flags |= GLO_FF_DEPTH_24; else flags |= GLO_FF_DEPTH_32; // Stencil - if (stencilSize>0) + if (stencilSize > 0) flags |= GLO_FF_STENCIL_8; return flags; } -void glo_geometry_get_from_glx(const int* attrib_list, int* width, int* height) +void glo_geometry_get_from_glx(const int *attrib_list, int *width, int *height) { - while ( *attrib_list ) - { - switch (*attrib_list) - { - case GLX_WIDTH: - *width = attrib_list[1]; - break; - case GLX_HEIGHT: - *height = attrib_list[1]; - break; - default: - fprintf(stderr, "Should not pass any attribs except for width and height for glXCreiatePixmap. \n"); + while (*attrib_list) { + switch (*attrib_list) { + case GLX_WIDTH: + *width = attrib_list[1]; + break; + case GLX_HEIGHT: + *height = attrib_list[1]; + break; + default: + fprintf(stderr, + "Should not pass any attribs except for width and height for glXCreiatePixmap. \n"); } attrib_list += 2; } } void glo_surface_getcontents_readpixels(int formatFlags, int stride, int bpp, - int width, int height, void *data, int noflip) { + int width, int height, void *data, + int noflip) +{ int glFormat, glType, rl, pa; static int once; glo_flags_get_readpixel_type(formatFlags, &glFormat, &glType); - switch(bpp) { - case 24: - if(glFormat != GL_BGR) { - if(!once) { - fprintf(stderr, "Warning: compressing alpha\n"); - once = 1; - } - glFormat = GL_BGR; - } - break; - case 32: - if(glFormat != GL_BGRA) { - fprintf(stderr, "Warning: expanding alpha!\n"); - glFormat = GL_BGRA; + switch (bpp) { + case 24: + if (glFormat != GL_BGR) { + if (!once) { + fprintf(stderr, "Warning: compressing alpha\n"); + once = 1; } - break; - default: - fprintf(stderr, "Warning: unsupported colourdepth\n"); - break; + glFormat = GL_BGR; + } + break; + case 32: + if (glFormat != GL_BGRA) { + fprintf(stderr, "Warning: expanding alpha!\n"); + glFormat = GL_BGRA; + } + break; + default: + fprintf(stderr, "Warning: unsupported colourdepth\n"); + break; } // Save guest processes GL state before we ReadPixels() @@ -403,23 +423,23 @@ void glo_surface_getcontents_readpixels(int formatFlags, int stride, int bpp, glPixelStorei(GL_PACK_ALIGNMENT, 4); #ifdef GETCONTENTS_INDIVIDUAL - GLubyte *b = (GLubyte *)data; + GLubyte *b = (GLubyte *) data; int irow; - for(irow = height-1 ; irow >= 0 ; irow--) { + for (irow = height - 1; irow >= 0; irow--) { glReadPixels(0, irow, width, 1, glFormat, glType, b); b += stride; } #else // Faster buffer flip - GLubyte *b = (GLubyte *)data; - GLubyte *c = &((GLubyte *)data)[stride*(height-1)]; - GLubyte *tmp = (GLubyte*)g_malloc(stride); + GLubyte *b = (GLubyte *) data; + GLubyte *c = &((GLubyte *) data)[stride * (height - 1)]; + GLubyte *tmp = (GLubyte *) g_malloc(stride); int irow; glReadPixels(0, 0, width, height, glFormat, glType, data); if (noflip == 0) { - for(irow = 0; irow < height/2; irow++) { + for (irow = 0; irow < height / 2; irow++) { memcpy(tmp, b, stride); memcpy(b, c, stride); memcpy(c, tmp, stride); @@ -436,54 +456,72 @@ void glo_surface_getcontents_readpixels(int formatFlags, int stride, int bpp, glPixelStorei(GL_PACK_ALIGNMENT, pa); } -int glo_get_glx_from_flags(int formatFlags, int glxEnum) { +int glo_get_glx_from_flags(int formatFlags, int glxEnum) +{ int rgba[4]; glo_flags_get_rgba_bits(formatFlags, rgba); switch (glxEnum) { - case GLX_USE_GL: return 1; - case GLX_BUFFER_SIZE: - return glo_flags_get_bytes_per_pixel(formatFlags)*8; - case GLX_LEVEL: return 0; - case GLX_RGBA: return formatFlags & GLO_FF_ALPHA; - case GLX_DOUBLEBUFFER: return 1; - case GLX_STEREO: return 0; - case GLX_AUX_BUFFERS: return 0; - case GLX_RED_SIZE: return rgba[0]; - case GLX_GREEN_SIZE: return rgba[1]; - case GLX_BLUE_SIZE: return rgba[2]; - case GLX_ALPHA_SIZE: return rgba[3]; - case GLX_DEPTH_SIZE: return glo_flags_get_depth_bits(formatFlags); - case GLX_STENCIL_SIZE: return glo_flags_get_stencil_bits(formatFlags); - case GLX_ACCUM_RED_SIZE: - case GLX_ACCUM_GREEN_SIZE: - case GLX_ACCUM_BLUE_SIZE: - case GLX_ACCUM_ALPHA_SIZE: - return 0; + case GLX_USE_GL: + return 1; + case GLX_BUFFER_SIZE: + return glo_flags_get_bytes_per_pixel(formatFlags) * 8; + case GLX_LEVEL: + return 0; + case GLX_RGBA: + return formatFlags & GLO_FF_ALPHA; + case GLX_DOUBLEBUFFER: + return 1; + case GLX_STEREO: + return 0; + case GLX_AUX_BUFFERS: + return 0; + case GLX_RED_SIZE: + return rgba[0]; + case GLX_GREEN_SIZE: + return rgba[1]; + case GLX_BLUE_SIZE: + return rgba[2]; + case GLX_ALPHA_SIZE: + return rgba[3]; + case GLX_DEPTH_SIZE: + return glo_flags_get_depth_bits(formatFlags); + case GLX_STENCIL_SIZE: + return glo_flags_get_stencil_bits(formatFlags); + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + case GLX_ACCUM_ALPHA_SIZE: + return 0; //the attributes for glXGetFBConfigAttrib - case GLX_FBCONFIG_ID: return 0; - case GLX_RENDER_TYPE: return GLX_RGBA_BIT; - case GLX_DRAWABLE_TYPE: return GLX_WINDOW_BIT; - case GLX_X_RENDERABLE: return 1; - case GLX_VISUAL_ID: - case GLX_X_VISUAL_TYPE: - // the real value is obtained in client side. - return 0; - case GLX_CONFIG_CAVEAT: return GLX_NONE; - case GLX_TRANSPARENT_TYPE: return GLX_NONE; - case GLX_TRANSPARENT_INDEX_VALUE: - case GLX_TRANSPARENT_RED_VALUE: - case GLX_TRANSPARENT_GREEN_VALUE: - case GLX_TRANSPARENT_BLUE_VALUE: - case GLX_TRANSPARENT_ALPHA_VALUE: - return 0; - case GLX_MAX_PBUFFER_WIDTH: - case GLX_MAX_PBUFFER_HEIGHT: - case GLX_MAX_PBUFFER_PIXELS: - return 0; - default: - return 0; + case GLX_FBCONFIG_ID: + return 0; + case GLX_RENDER_TYPE: + return GLX_RGBA_BIT; + case GLX_DRAWABLE_TYPE: + return GLX_WINDOW_BIT; + case GLX_X_RENDERABLE: + return 1; + case GLX_VISUAL_ID: + case GLX_X_VISUAL_TYPE: + // the real value is obtained in client side. + return 0; + case GLX_CONFIG_CAVEAT: + return GLX_NONE; + case GLX_TRANSPARENT_TYPE: + return GLX_NONE; + case GLX_TRANSPARENT_INDEX_VALUE: + case GLX_TRANSPARENT_RED_VALUE: + case GLX_TRANSPARENT_GREEN_VALUE: + case GLX_TRANSPARENT_BLUE_VALUE: + case GLX_TRANSPARENT_ALPHA_VALUE: + return 0; + case GLX_MAX_PBUFFER_WIDTH: + case GLX_MAX_PBUFFER_HEIGHT: + case GLX_MAX_PBUFFER_PIXELS: + return 0; + default: + return 0; } return 0; } - diff --git a/tizen/src/hw/gloffscreen_glx.c b/tizen/src/hw/gloffscreen_glx.c index a2ec3b2cc0..16df56cc00 100644 --- a/tizen/src/hw/gloffscreen_glx.c +++ b/tizen/src/hw/gloffscreen_glx.c @@ -44,262 +44,294 @@ #endif struct GloMain { - Display *dpy; - int use_ximage; + Display *dpy; + int use_ximage; }; struct GloMain glo; int glo_inited = 0; struct _GloContext { - GLuint formatFlags; + GLuint formatFlags; - GLXFBConfig fbConfig; - GLXContext context; + GLXFBConfig fbConfig; + GLXContext context; }; struct _GloSurface { - GLuint width; - GLuint height; + GLuint width; + GLuint height; - GloContext *context; - Pixmap xPixmap; - GLXPixmap glxPixmap; + GloContext *context; + Pixmap xPixmap; + GLXPixmap glxPixmap; - // For use by the 'fast' copy code. - XImage *image; - XShmSegmentInfo shminfo; + // For use by the 'fast' copy code. + XImage *image; + XShmSegmentInfo shminfo; }; extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, - int bpp, int width, int height, void *data, int noflip); + int bpp, int width, int height, + void *data, int noflip); static void glo_test_readback_methods(void); /* ------------------------------------------------------------------------ */ -int glo_initialised(void) { - return glo_inited; +int glo_initialised(void) +{ + return glo_inited; } /* Initialise gloffscreen */ -int glo_init(void) { +int glo_init(void) +{ if (glo_inited) { - printf( "gloffscreen already inited\n" ); + printf("gloffscreen already inited\n"); //exit( EXIT_FAILURE ); - return 1; + return 1; } /* Open a connection to the X server */ - glo.dpy = XOpenDisplay( NULL ); - if ( glo.dpy == NULL ) { - printf( "Unable to open a connection to the X server\n" ); + glo.dpy = XOpenDisplay(NULL); + if (glo.dpy == NULL) { + printf("Unable to open a connection to the X server\n"); //exit( EXIT_FAILURE ); - return 1; + return 1; } glo_inited = 1; glo_test_readback_methods(); - return 0; + return 0; } /* Uninitialise gloffscreen */ -void glo_kill(void) { +void glo_kill(void) +{ XCloseDisplay(glo.dpy); glo.dpy = NULL; } - /* Like wglGetProcAddress/glxGetProcAddress */ -void *glo_getprocaddress(const char *procName) { +void *glo_getprocaddress(const char *procName) +{ if (!glo_inited) - glo_init(); - return glXGetProcAddressARB((const GLubyte *) procName); + glo_init(); + return glXGetProcAddressARB((const GLubyte *)procName); } /* ------------------------------------------------------------------------ */ /* Create a light-weight context just for creating surface */ -GloContext *__glo_context_create(int formatFlags) { - - GLXFBConfig *fbConfigs; - int numReturned; - GloContext *context; - int rgbaBits[4]; - int bufferAttributes[] = { - GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 0, - GLX_STENCIL_SIZE, 0, - None - }; - - if (!glo_inited) - glo_init(); - - // set up the surface format from the flags we were given - glo_flags_get_rgba_bits(formatFlags, rgbaBits); - bufferAttributes[5] = rgbaBits[0]; - bufferAttributes[7] = rgbaBits[1]; - bufferAttributes[9] = rgbaBits[2]; - bufferAttributes[11] = rgbaBits[3]; - bufferAttributes[13] = glo_flags_get_depth_bits(formatFlags); - bufferAttributes[15] = glo_flags_get_stencil_bits(formatFlags); - - //printf("Got R%d, G%d, B%d, A%d\n", rgbaBits[0], rgbaBits[1], rgbaBits[2], rgbaBits[3]); - - fbConfigs = glXChooseFBConfig( glo.dpy, DefaultScreen(glo.dpy), - bufferAttributes, &numReturned ); - if (numReturned==0) { - printf( "No matching configs found.\n" ); - //exit( EXIT_FAILURE ); - return NULL; - } - context = (GloContext*)qemu_malloc(sizeof(GloContext)); - memset(context, 0, sizeof(GloContext)); - context->formatFlags = formatFlags; - context->fbConfig = fbConfigs[0]; - - return context; +GloContext *__glo_context_create(int formatFlags) +{ + + GLXFBConfig *fbConfigs; + int numReturned; + GloContext *context; + int rgbaBits[4]; + int bufferAttributes[] = { + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 0, + GLX_STENCIL_SIZE, 0, + None + }; + + if (!glo_inited) + glo_init(); + + // set up the surface format from the flags we were given + glo_flags_get_rgba_bits(formatFlags, rgbaBits); + bufferAttributes[5] = rgbaBits[0]; + bufferAttributes[7] = rgbaBits[1]; + bufferAttributes[9] = rgbaBits[2]; + bufferAttributes[11] = rgbaBits[3]; + bufferAttributes[13] = glo_flags_get_depth_bits(formatFlags); + bufferAttributes[15] = glo_flags_get_stencil_bits(formatFlags); + + //printf("Got R%d, G%d, B%d, A%d\n", rgbaBits[0], rgbaBits[1], rgbaBits[2], rgbaBits[3]); + + fbConfigs = glXChooseFBConfig(glo.dpy, DefaultScreen(glo.dpy), + bufferAttributes, &numReturned); + if (numReturned == 0) { + printf("No matching configs found.\n"); + //exit( EXIT_FAILURE ); + return NULL; + } + context = (GloContext *) qemu_malloc(sizeof(GloContext)); + memset(context, 0, sizeof(GloContext)); + context->formatFlags = formatFlags; + context->fbConfig = fbConfigs[0]; + + return context; } /* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */ -GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { +GloContext *glo_context_create(int formatFlags, GloContext * shareLists) +{ - GloContext *context = __glo_context_create(formatFlags); + GloContext *context = __glo_context_create(formatFlags); - if (!context) { - return NULL; - } + if (!context) { + return NULL; + } - /* Create a GLX context for OpenGL rendering */ - context->context = glXCreateNewContext(glo.dpy, context->fbConfig, - GLX_RGBA_TYPE, - shareLists ? shareLists->context: NULL, - True ); + /* Create a GLX context for OpenGL rendering */ + context->context = glXCreateNewContext(glo.dpy, context->fbConfig, + GLX_RGBA_TYPE, + shareLists ? shareLists-> + context : NULL, True); - if (!context->context) { - printf( "glXCreateNewContext failed\n" ); - //exit( EXIT_FAILURE ); - return NULL; - } + if (!context->context) { + printf("glXCreateNewContext failed\n"); + //exit( EXIT_FAILURE ); + return NULL; + } - return context; + return context; } /* Destroy a previouslu created OpenGL context */ -void glo_context_destroy(GloContext *context) { - if (!context) return; - // TODO: check for GloSurfaces using this? - glXDestroyContext( glo.dpy, context->context); - qemu_free(context); +void glo_context_destroy(GloContext * context) +{ + if (!context) + return; + // TODO: check for GloSurfaces using this? + glXDestroyContext(glo.dpy, context->context); + qemu_free(context); } -static void glo_surface_free_xshm_image(GloSurface *surface) { - XShmDetach(glo.dpy, &surface->shminfo); - surface->image->data = NULL; - XDestroyImage(surface->image); - shmdt(surface->shminfo.shmaddr); - shmctl(surface->shminfo.shmid, IPC_RMID, NULL); +static void glo_surface_free_xshm_image(GloSurface * surface) +{ + XShmDetach(glo.dpy, &surface->shminfo); + surface->image->data = NULL; + XDestroyImage(surface->image); + shmdt(surface->shminfo.shmaddr); + shmctl(surface->shminfo.shmid, IPC_RMID, NULL); } -//FIXMEIM - handle failure to allocate. -static void glo_surface_try_alloc_xshm_image(GloSurface *surface) { - if(surface->image) - glo_surface_free_xshm_image(surface); +static int glo_surface_try_alloc_xshm_image(GloSurface * surface) +{ + if (surface->image) + glo_surface_free_xshm_image(surface); surface->image = - XShmCreateImage(glo.dpy, DefaultVisual(glo.dpy, 0), 24, ZPixmap, NULL, - &surface->shminfo, surface->width, surface->height); + XShmCreateImage(glo.dpy, DefaultVisual(glo.dpy, 0), 24, ZPixmap, NULL, + &surface->shminfo, surface->width, surface->height); + if (!surface->image) + return -1; + surface->shminfo.shmid = shmget(IPC_PRIVATE, surface->image->bytes_per_line * - surface->height, - IPC_CREAT | 0777); + surface->height, IPC_CREAT | 0777); + if (surface->shminfo.shmid < 0) + return -1; + surface->shminfo.shmaddr = shmat(surface->shminfo.shmid, NULL, 0); + if (surface->shminfo.shmaddr == (void *)-1) + return -1; + surface->image->data = surface->shminfo.shmaddr; surface->shminfo.readOnly = False; XShmAttach(glo.dpy, &surface->shminfo); + + return 0; } /* ------------------------------------------------------------------------ */ /* Update the context in surface and handle previous context */ -int glo_surface_update_context(GloSurface *surface, GloContext *context) - { +int glo_surface_update_context(GloSurface * surface, GloContext * context) +{ /* If previous context is light-weight context, just free it. If previous * context is valid one binded with surface via MakeCurrent, we need unbind * from original glstate */ int prev_context_valid = 0; - if ( surface->context ) - { + if (surface->context) { prev_context_valid = (surface->context->context != 0); - if ( !prev_context_valid ) /* light-weight context */ + if (!prev_context_valid) /* light-weight context */ g_free(surface->context); } surface->context = context; return prev_context_valid; } - /* Create a surface with given width and height, formatflags are from the * GLO_ constants */ -GloSurface *glo_surface_create(int width, int height, GloContext *context) { - GloSurface *surface; +GloSurface *glo_surface_create(int width, int height, GloContext * context) +{ + GloSurface *surface; - if (!context) return 0; + if (!context) + return 0; - surface = (GloSurface*)qemu_malloc(sizeof(GloSurface)); + surface = (GloSurface *) qemu_malloc(sizeof(GloSurface)); memset(surface, 0, sizeof(GloSurface)); surface->width = width; surface->height = height; surface->context = context; - surface->xPixmap = XCreatePixmap( glo.dpy, DefaultRootWindow(glo.dpy), - width, height, - glo_flags_get_bytes_per_pixel(context->formatFlags)*8); + surface->xPixmap = XCreatePixmap(glo.dpy, DefaultRootWindow(glo.dpy), + width, height, + glo_flags_get_bytes_per_pixel(context-> + formatFlags) + * 8); if (!surface->xPixmap) { - printf( "XCreatePixmap failed\n" ); - //exit( EXIT_FAILURE ); - return NULL; + printf("XCreatePixmap failed\n"); + qemu_free(surface); + return NULL; } /* Create a GLX window to associate the frame buffer configuration - ** with the created X window */ - surface->glxPixmap = glXCreatePixmap( glo.dpy, context->fbConfig, surface->xPixmap, NULL ); + ** with the created X window */ + surface->glxPixmap = + glXCreatePixmap(glo.dpy, context->fbConfig, surface->xPixmap, NULL); if (!surface->glxPixmap) { - printf( "glXCreatePixmap failed\n" ); - //exit( EXIT_FAILURE ); - return NULL; + printf("glXCreatePixmap failed\n"); + XFreePixmap(glo.dpy, surface->xPixmap); + qemu_free(surface); + return NULL; } - // If we're using XImages to pull the data from the graphics card... - glo_surface_try_alloc_xshm_image(surface); + if (glo_surface_try_alloc_xshm_image(surface) < 0) { + printf("Failed to allocate shm image\n"); + glXDestroyPixmap(glo.dpy, surface->glxPixmap); + XFreePixmap(glo.dpy, surface->xPixmap); + qemu_free(surface); + return NULL; + } return surface; } /* Destroy the given surface */ -void glo_surface_destroy(GloSurface *surface) { - glXDestroyPixmap( glo.dpy, surface->glxPixmap); - XFreePixmap( glo.dpy, surface->xPixmap); - if(surface->image) - glo_surface_free_xshm_image(surface); +void glo_surface_destroy(GloSurface * surface) +{ + glXDestroyPixmap(glo.dpy, surface->glxPixmap); + XFreePixmap(glo.dpy, surface->xPixmap); + if (surface->image) + glo_surface_free_xshm_image(surface); qemu_free(surface); } /* Make the given surface current */ -int glo_surface_makecurrent(GloSurface *surface) { +int glo_surface_makecurrent(GloSurface * surface) +{ int ret; if (!glo_inited) - glo_init(); + glo_init(); if (surface) { - ret = glXMakeCurrent(glo.dpy, surface->glxPixmap, surface->context->context); + ret = + glXMakeCurrent(glo.dpy, surface->glxPixmap, + surface->context->context); } else { - ret = glXMakeCurrent(glo.dpy, 0, NULL); + ret = glXMakeCurrent(glo.dpy, 0, NULL); } return ret; @@ -315,63 +347,67 @@ int glo_surface_makecurrent(GloSurface *surface) { */ /* Get the contents of the given surface */ -void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, void *data) { +void glo_surface_getcontents(GloSurface * surface, int stride, int bpp, + void *data) +{ static int once; XImage *img; if (!surface) - return; - - if(glo.use_ximage) { - glXWaitGL(); - - if(surface->image) { - XShmGetImage (glo.dpy, surface->xPixmap, surface->image, 0, 0, AllPlanes); - img = surface->image; - } - else { - img = XGetImage(glo.dpy, surface->xPixmap, 0, 0, surface->width, surface->height, AllPlanes, ZPixmap); - } - - if (img) { - if(bpp != 32 && bpp != 24 && !once) { - fprintf(stderr, "Warning: unsupported colourdepth\n"); - once = 1; + return; + + if (glo.use_ximage) { + glXWaitGL(); + + if (surface->image) { + XShmGetImage(glo.dpy, surface->xPixmap, surface->image, 0, 0, + AllPlanes); + img = surface->image; + } else { + img = + XGetImage(glo.dpy, surface->xPixmap, 0, 0, surface->width, + surface->height, AllPlanes, ZPixmap); } - if(bpp == img->bits_per_pixel && stride == img->bytes_per_line) - { - memcpy(data, img->data, stride * surface->height); - } - else - { - int x, y; - for(y = 0 ; y < surface->height ; y++) { - for(x = 0 ; x < surface->width ; x++) { - char *src = ((char*)img->data) + (x*(img->bits_per_pixel/8)) + (y*img->bytes_per_line); - char *dst = ((char*)data) + x*(bpp/8) + (y*stride); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - if(bpp == 32) - dst[3] = 0xff; // if guest is 32 bit and host is 24 + if (img) { + if (bpp != 32 && bpp != 24 && !once) { + fprintf(stderr, "Warning: unsupported colourdepth\n"); + once = 1; } - } + + if (bpp == img->bits_per_pixel && stride == img->bytes_per_line) { + memcpy(data, img->data, stride * surface->height); + } else { + int x, y; + for (y = 0; y < surface->height; y++) { + for (x = 0; x < surface->width; x++) { + char *src = + ((char *)img->data) + + (x * (img->bits_per_pixel / 8)) + + (y * img->bytes_per_line); + char *dst = + ((char *)data) + x * (bpp / 8) + (y * stride); + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + if (bpp == 32) + dst[3] = 0xff; // if guest is 32 bit and host is 24 + } + } + } + + // If we're not using Shm + if (!surface->image) + XDestroyImage(img); + + return; // We're done. } - - // If we're not using Shm - if(!surface->image) - XDestroyImage(img); - - return; // We're done. - } - // Uh oh... better fallback. Perhaps get glo.use_ximage to 0? - } - - // Compatible / fallback method. - glo_surface_getcontents_readpixels(surface->context->formatFlags, - stride, bpp, surface->width, - surface->height, data, 0); + // Uh oh... better fallback. Perhaps get glo.use_ximage to 0? + } + // Compatible / fallback method. + glo_surface_getcontents_readpixels(surface->context->formatFlags, + stride, bpp, surface->width, + surface->height, data, 0); } // while(0) { @@ -385,60 +421,65 @@ void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, void *dat // } /* Return the width and height of the given surface */ -void glo_surface_get_size(GloSurface *surface, int *width, int *height) { +void glo_surface_get_size(GloSurface * surface, int *width, int *height) +{ if (width) - *width = surface->width; + *width = surface->width; if (height) - *height = surface->height; + *height = surface->height; } /* Abstract glXQueryExtensionString() */ -const char *glo_glXQueryExtensionsString(void) { - return glXQueryExtensionsString(glo.dpy, 0); +const char *glo_glXQueryExtensionsString(void) +{ + return glXQueryExtensionsString(glo.dpy, 0); } - #define TX (17) #define TY (16) -static int glo_can_readback(void) { +static int glo_can_readback(void) +{ GloContext *context; GloSurface *surface; - unsigned char *datain = (unsigned char *)qemu_malloc(4*TX*TY); - unsigned char *datain_flip = (unsigned char *)qemu_malloc(4*TX*TY); // flipped input data (for GL) - unsigned char *dataout = (unsigned char *)qemu_malloc(4*TX*TY); + unsigned char *datain = (unsigned char *)qemu_malloc(4 * TX * TY); + unsigned char *datain_flip = (unsigned char *)qemu_malloc(4 * TX * TY); // flipped input data (for GL) + unsigned char *dataout = (unsigned char *)qemu_malloc(4 * TX * TY); unsigned char *p; - int x,y; + int x, y; const int bufferAttributes[] = { - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 0, - GLX_STENCIL_SIZE, 0, - 0, - }; + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 0, + GLX_STENCIL_SIZE, 0, + 0, + }; int bufferFlags = glo_flags_get_from_glx(bufferAttributes, 0); int bpp = glo_flags_get_bytes_per_pixel(bufferFlags); int glFormat, glType; - memset(datain_flip, 0, TX*TY*4); - memset(datain, 0, TX*TY*4); + memset(datain_flip, 0, TX * TY * 4); + memset(datain, 0, TX * TY * 4); p = datain; - for (y=0;y2) p[2] = 0; - if (bpp>3) p[3] = 0xFF; - p+=bpp; - } - memcpy(&datain_flip[((TY-1)-y)*bpp*TX], &datain[y*bpp*TX], bpp*TX); + for (y = 0; y < TY; y++) { + for (x = 0; x < TX; x++) { + p[0] = x; + p[1] = y; + //if (y&1) { p[0]=0; p[1]=0; } + if (bpp > 2) + p[2] = 0; + if (bpp > 3) + p[3] = 0xFF; + p += bpp; + } + memcpy(&datain_flip[((TY - 1) - y) * bpp * TX], &datain[y * bpp * TX], + bpp * TX); } context = glo_context_create(bufferFlags, 0); @@ -449,33 +490,35 @@ static int glo_can_readback(void) { glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0,TX, 0,TY, 0, 1); + glOrtho(0, TX, 0, TY, 0, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glRasterPos2f(0,0); + glRasterPos2f(0, 0); glo_flags_get_readpixel_type(bufferFlags, &glFormat, &glType); - glDrawPixels(TX,TY,glFormat, glType, datain_flip); + glDrawPixels(TX, TY, glFormat, glType, datain_flip); glFlush(); - memset(dataout, 0, bpp*TX*TY); + memset(dataout, 0, bpp * TX * TY); - glo_surface_getcontents(surface, TX*4, bpp*8, dataout); + glo_surface_getcontents(surface, TX * 4, bpp * 8, dataout); glo_surface_destroy(surface); glo_context_destroy(context); - if (memcmp(datain, dataout, bpp*TX*TY)==0) + if (memcmp(datain, dataout, bpp * TX * TY) == 0) return 1; return 0; } -static void glo_test_readback_methods(void) { +static void glo_test_readback_methods(void) +{ glo.use_ximage = 1; - if(!glo_can_readback()) - glo.use_ximage = 0; + if (!glo_can_readback()) + glo.use_ximage = 0; - fprintf(stderr, "VM GL: Using %s readback\n", glo.use_ximage?"XImage":"glReadPixels"); + fprintf(stderr, "VM GL: Using %s readback\n", + glo.use_ximage ? "XImage" : "glReadPixels"); } #endif diff --git a/tizen/src/hw/gloffscreen_test.c b/tizen/src/hw/gloffscreen_test.c index 2799421938..72c0b4f406 100644 --- a/tizen/src/hw/gloffscreen_test.c +++ b/tizen/src/hw/gloffscreen_test.c @@ -34,7 +34,7 @@ #include #include #include -#elif __APPLE__ +#elif defined __APPLE__ #include #include #else @@ -75,7 +75,8 @@ #define CHECK_SUCCESS 0 #define CHECK_FAIL 1 -int gl_acceleration_capability_check (void) { +int gl_acceleration_capability_check(void) +{ //int test_failure = 0; GloContext *context; GloSurface *surface; @@ -83,20 +84,20 @@ int gl_acceleration_capability_check (void) { unsigned char *datain_flip; unsigned char *dataout; unsigned char *p; - int x,y; + int x, y; const int bufferAttributes[] = { - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 0, - GLX_STENCIL_SIZE, 0, - 0, - }; + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 0, + GLX_STENCIL_SIZE, 0, + 0, + }; #ifdef MANGLE_OPENGL_SYMBOLS if (mgl_load_symbols("libGL.so.1")) { - return CHECK_FAIL; + return CHECK_FAIL; } #endif @@ -108,48 +109,53 @@ int gl_acceleration_capability_check (void) { // test failed. return 1; } -*/ - datain = (unsigned char *)malloc(4*TX*TY); - datain_flip = (unsigned char *)malloc(4*TX*TY); +*/ + datain = (unsigned char *)malloc(4 * TX * TY); + datain_flip = (unsigned char *)malloc(4 * TX * TY); - memset(datain, 0, TX*TY*4); - memset(datain_flip, 0, TX*TY*4); + memset(datain, 0, TX * TY * 4); + memset(datain_flip, 0, TX * TY * 4); p = datain; - for (y=0;y2) p[2] = 0; - if (bpp>3) p[3] = 0xFF; - p+=bpp; - } - memcpy(&datain_flip[((TY-1)-y)*bpp*TX], &datain[y*bpp*TX], bpp*TX); + for (y = 0; y < TY; y++) { + for (x = 0; x < TX; x++) { + p[0] = x; + p[1] = y; + //if (y&1) { p[0]=0; p[1]=0; } + if (bpp > 2) + p[2] = 0; + if (bpp > 3) + p[3] = 0xFF; + p += bpp; + } + memcpy(&datain_flip[((TY - 1) - y) * bpp * TX], &datain[y * bpp * TX], + bpp * TX); } if (glo_init() != 0) { - printf ("Host does not have GL hardware acceleration!(glo_init() failed)\n"); - free (datain); - free (datain_flip); - return CHECK_FAIL; + printf + ("Host does not have GL hardware acceleration!(glo_init() failed)\n"); + free(datain); + free(datain_flip); + return CHECK_FAIL; } - // new surface context = glo_context_create(bufferFlags, 0); - if (context == NULL) { - printf ("Host does not have GL hardware acceleration!(context_create() failed)\n"); - free (datain); - free (datain_flip); - return CHECK_FAIL; + if (context == NULL) { + printf + ("Host does not have GL hardware acceleration!(context_create() failed)\n"); + free(datain); + free(datain_flip); + return CHECK_FAIL; } surface = glo_surface_create(TX, TY, context); - if (surface == NULL) { - printf ("Host does not have GL hardware acceleration!(surface_create() failed)\n"); - free (datain); - free (datain_flip); - return CHECK_FAIL; + if (surface == NULL) { + printf + ("Host does not have GL hardware acceleration!(surface_create() failed)\n"); + free(datain); + free(datain_flip); + return CHECK_FAIL; } glo_surface_makecurrent(surface); @@ -158,48 +164,48 @@ int gl_acceleration_capability_check (void) { printf("GL VERSION %s\n", glGetString(GL_VERSION)); //printf("GLSL VERSION %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); - if (strstr((const char*)glGetString(GL_RENDERER), "Software")) { - printf ("Host does not have GL hardware acceleration!(No host gl driver)\n"); - free (datain); - free (datain_flip); - return CHECK_FAIL; + if (strstr((const char *)glGetString(GL_RENDERER), "Software")) { + printf + ("Host does not have GL hardware acceleration!(No host gl driver)\n"); + free(datain); + free(datain_flip); + return CHECK_FAIL; } - // fill with stuff (in correctly ordered way) glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0,TX, 0,TY, 0, 1); + glOrtho(0, TX, 0, TY, 0, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glRasterPos2f(0,0); + glRasterPos2f(0, 0); glo_flags_get_readpixel_type(bufferFlags, &glFormat, &glType); printf("glFormat: 0x%08X glType: 0x%08X\n", glFormat, glType); - glDrawPixels(TX,TY,glFormat, glType, datain_flip); + glDrawPixels(TX, TY, glFormat, glType, datain_flip); glFlush(); - - dataout = (unsigned char *)malloc(4*TX*TY); - memset(dataout, 0, bpp*TX*TY); - glo_surface_getcontents(surface, TX*bpp, bpp*8, dataout); + dataout = (unsigned char *)malloc(4 * TX * TY); + memset(dataout, 0, bpp * TX * TY); + + glo_surface_getcontents(surface, TX * bpp, bpp * 8, dataout); // destroy surface glo_surface_destroy(surface); glo_context_destroy(context); // compare - if (memcmp(datain, dataout, bpp*TX*TY)!=0) { - printf ("Host does not have GL hardware acceleration!(datain != dataout)\n"); - free (datain); - free (datain_flip); - free (dataout); - return CHECK_FAIL; + if (memcmp(datain, dataout, bpp * TX * TY) != 0) { + printf + ("Host does not have GL hardware acceleration!(datain != dataout)\n"); + free(datain); + free(datain_flip); + free(dataout); + return CHECK_FAIL; } - //glo_kill(); //printf ("Testing %s\n", (test_failure ? "FAILED" : "PASSED")); - free (datain); - free (datain_flip); - free (dataout); + free(datain); + free(datain_flip); + free(dataout); - return CHECK_SUCCESS; + return CHECK_SUCCESS; } diff --git a/tizen/src/hw/gloffscreen_test.h b/tizen/src/hw/gloffscreen_test.h index 452704340c..fd974741ee 100644 --- a/tizen/src/hw/gloffscreen_test.h +++ b/tizen/src/hw/gloffscreen_test.h @@ -31,4 +31,4 @@ int gl_acceleration_capability_check(void); -#endif /* __GLOFFSCREEN_TEST_H__ */ +#endif /* __GLOFFSCREEN_TEST_H__ */ diff --git a/tizen/src/hw/gloffscreen_wgl.c b/tizen/src/hw/gloffscreen_wgl.c index 610a911f7e..8467432ded 100644 --- a/tizen/src/hw/gloffscreen_wgl.c +++ b/tizen/src/hw/gloffscreen_wgl.c @@ -33,11 +33,12 @@ #include #include +#include #include #include #include "GL/wglext.h" -#define MAX_ATTRIBS 12 /*Max attributes of pixel format we need*/ +#define MAX_ATTRIBS 12 /*Max attributes of pixel format we need */ #ifdef MANGLE_OPENGL_SYMBOLS #include "gl_mangled.h" @@ -58,33 +59,33 @@ enum { */ struct GloMain { - HINSTANCE hInstance; - HDC hDC; - HWND hWnd; /* Our hidden window */ - HGLRC hContext; + HINSTANCE hInstance; + HDC hDC; + HWND hWnd; /* Our hidden window */ + HGLRC hContext; }; struct GloMain glo; int glo_inited = 0; int Render_texture_support = 0; struct _GloContext { - int formatFlags; + int formatFlags; /* Pixel format returned by wglChoosePixelFormat */ - int wglPixelFormat; + int wglPixelFormat; /* We need a pbuffer to make a context of the right pixelformat :( */ - HPBUFFERARB hPBuffer; - HDC hDC; - HGLRC hContext; + HPBUFFERARB hPBuffer; + HDC hDC; + HGLRC hContext; }; struct _GloSurface { - GLuint width; - GLuint height; + GLuint width; + GLuint height; - GloContext *context; - HPBUFFERARB hPBuffer; - HDC hDC; + GloContext *context; + HPBUFFERARB hPBuffer; + HDC hDC; }; #define GLO_WINDOW_CLASS "QEmuGLClass" @@ -101,62 +102,71 @@ PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB; /* ------------------------------------------------------------------------ */ -extern const char *glo_glXQueryExtensionsString(void); - extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, - int bpp, int width, int height, void *data, int noflip); + int bpp, int width, int height, + void *data, int noflip); /* ------------------------------------------------------------------------ */ -int glo_initialised(void) { +int glo_initialised(void) +{ return glo_inited; } +#if 0 /* Sanity test of the host GL capabilities to see whether the gl offscreen * could be well supported */ -int glo_sanity_test (void) { +int glo_sanity_test(void) +{ PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB; PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB; PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB; PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB; - wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); - wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB"); - wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB"); - wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB"); - wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress("wglDestroyPbufferARB"); - if (!wglChoosePixelFormatARB || - !wglGetPbufferDCARB || - !wglReleasePbufferDCARB || - !wglCreatePbufferARB || - !wglDestroyPbufferARB) { - fprintf (stderr, "Unable to load the required WGL extensions\n"); + wglChoosePixelFormatARB = + (PFNWGLCHOOSEPIXELFORMATARBPROC) + wglGetProcAddress("wglChoosePixelFormatARB"); + wglGetPbufferDCARB = + (PFNWGLGETPBUFFERDCARBPROC) wglGetProcAddress("wglGetPbufferDCARB"); + wglReleasePbufferDCARB = + (PFNWGLRELEASEPBUFFERDCARBPROC) + wglGetProcAddress("wglReleasePbufferDCARB"); + wglCreatePbufferARB = + (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB"); + wglDestroyPbufferARB = + (PFNWGLDESTROYPBUFFERARBPROC) wglGetProcAddress("wglDestroyPbufferARB"); + if (!wglChoosePixelFormatARB || !wglGetPbufferDCARB + || !wglReleasePbufferDCARB || !wglCreatePbufferARB + || !wglDestroyPbufferARB) { + fprintf(stderr, "Unable to load the required WGL extensions\n"); return 1; } // check the shader support. It is for mcompositor to run. if (!wglGetProcAddress("glShaderSource")) { - fprintf (stderr, "Unable to find shader support\n"); + fprintf(stderr, "Unable to find shader support\n"); return 1; } return 0; } +#endif /* Initialise gloffscreen */ -int glo_init(void) { +int glo_init(void) +{ WNDCLASSEX wcx; PIXELFORMATDESCRIPTOR pfd; - char *ext_str; + const char *ext_str; if (glo_inited) { - printf( "gloffscreen already inited\n" ); + printf("gloffscreen already inited\n"); //exit( EXIT_FAILURE ); - return 1; + return 1; } - glo.hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window + glo.hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window wcx.cbSize = sizeof(wcx); wcx.style = 0; @@ -167,22 +177,20 @@ int glo_init(void) { wcx.hIcon = NULL; wcx.hCursor = NULL; wcx.hbrBackground = NULL; - wcx.lpszMenuName = NULL; + wcx.lpszMenuName = NULL; wcx.lpszClassName = GLO_WINDOW_CLASS; wcx.hIconSm = NULL; RegisterClassEx(&wcx); - glo.hWnd = CreateWindow( - GLO_WINDOW_CLASS, - "QEmuGL", - 0,0,0,0,0, - (HWND)NULL, (HMENU)NULL, - glo.hInstance, - (LPVOID) NULL); + glo.hWnd = CreateWindow(GLO_WINDOW_CLASS, + "QEmuGL", + 0, 0, 0, 0, 0, + (HWND) NULL, (HMENU) NULL, + glo.hInstance, (LPVOID) NULL); if (!glo.hWnd) { - printf( "Unable to create window\n" ); + printf("Unable to create window\n"); //exit( EXIT_FAILURE ); - return 1; + return 1; } glo.hDC = GetDC(glo.hWnd); @@ -194,15 +202,16 @@ int glo_init(void) { pfd.cColorBits = 24; pfd.iLayerType = PFD_MAIN_PLANE; unsigned int pixelFormat = ChoosePixelFormat(glo.hDC, &pfd); - DescribePixelFormat(glo.hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + DescribePixelFormat(glo.hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), + &pfd); if (!SetPixelFormat(glo.hDC, pixelFormat, &pfd)) return 1; glo.hContext = wglCreateContext(glo.hDC); if (glo.hContext == NULL) { - printf( "Unable to create GL context\n" ); + printf("Unable to create GL context\n"); //exit( EXIT_FAILURE ); - return 1; + return 1; } wglMakeCurrent(glo.hDC, glo.hContext); @@ -210,64 +219,67 @@ int glo_init(void) { // Need to share lists AND copy state // load in the extensions we need - //const char *ext = wglGetExtensionsStringARB(hdc); + //const char *ext = wglGetExtensionsStringARB(hdc); //"WGL_ARB_pixel_format" "WGL_ARB_pbuffer" - wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); - wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB"); - wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB"); - wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB"); - wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress("wglDestroyPbufferARB"); - wglBindTexImageARB = (PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress("wglBindTexImageARB"); - wglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC)wglGetProcAddress("wglReleaseTexImageARB"); - wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); + wglChoosePixelFormatARB = + (PFNWGLCHOOSEPIXELFORMATARBPROC) + wglGetProcAddress("wglChoosePixelFormatARB"); + wglGetPbufferDCARB = + (PFNWGLGETPBUFFERDCARBPROC) wglGetProcAddress("wglGetPbufferDCARB"); + wglReleasePbufferDCARB = + (PFNWGLRELEASEPBUFFERDCARBPROC) + wglGetProcAddress("wglReleasePbufferDCARB"); + wglCreatePbufferARB = + (PFNWGLCREATEPBUFFERARBPROC) wglGetProcAddress("wglCreatePbufferARB"); + wglDestroyPbufferARB = + (PFNWGLDESTROYPBUFFERARBPROC) wglGetProcAddress("wglDestroyPbufferARB"); + wglBindTexImageARB = + (PFNWGLBINDTEXIMAGEARBPROC) wglGetProcAddress("wglBindTexImageARB"); + wglReleaseTexImageARB = + (PFNWGLRELEASETEXIMAGEARBPROC) + wglGetProcAddress("wglReleaseTexImageARB"); + wglGetExtensionsStringARB = + (PFNWGLGETEXTENSIONSSTRINGARBPROC) + wglGetProcAddress("wglGetExtensionsStringARB"); if (!wglChoosePixelFormatARB || !wglGetPbufferDCARB || !wglReleasePbufferDCARB || !wglCreatePbufferARB || - !wglDestroyPbufferARB || - !wglGetExtensionsStringARB ) { - printf( "Unable to load the required WGL extensions\n" ); + !wglDestroyPbufferARB || !wglGetExtensionsStringARB) { + printf("Unable to load the required WGL extensions\n"); //exit( EXIT_FAILURE ); - return 1; + return 1; + } + + if (wglGetExtensionsStringARB) { + ext_str = wglGetExtensionsStringARB(wglGetCurrentDC()); + if (ext_str == NULL) { + fprintf(stderr, "Failed tp get extensions string!\n"); + Render_texture_support = 0; + } else { + if (strstr(ext_str, "WGL_ARB_render_texture") != NULL) { + fprintf(stdout, "WGL_ARB_render_texture supported!\n"); + Render_texture_support = 1; + } else { + fprintf(stderr, "WGL_ARB_render_texture not supported!\n"); + Render_texture_support = 0; + } + } } - if(wglGetExtensionsStringARB) - { - ext_str = wglGetExtensionsStringARB(wglGetCurrentDC()); - if(ext_str == NULL) - { - fprintf(stderr, "Failed tp get extensions string!\n"); - Render_texture_support = 0; - } - else - { - if(strstr(ext_str, "WGL_ARB_render_texture") != NULL) - { - fprintf(stdout, "WGL_ARB_render_texture supported!\n"); - Render_texture_support = 1; - } - else - { - fprintf(stderr, "WGL_ARB_render_texture not supported!\n"); - Render_texture_support = 0; - } - } - } - - - if ( !wglBindTexImageARB || - !wglReleaseTexImageARB ) - fprintf (stderr, "Warning: no [Bind|Release]TexImageARB extensions.\n"); + if (!wglBindTexImageARB || !wglReleaseTexImageARB) + fprintf(stderr, "Warning: no [Bind|Release]TexImageARB extensions.\n"); glo_inited = 1; - return 0; + return 0; } /* Uninitialise gloffscreen */ -void glo_kill(void) { +void glo_kill(void) +{ if (glo.hContext) { wglMakeCurrent(NULL, NULL); wglDeleteContext(glo.hContext); @@ -284,395 +296,350 @@ void glo_kill(void) { UnregisterClass(GLO_WINDOW_CLASS, glo.hInstance); } -const char *glo_glXQueryExtensionsString(void) { +const char *glo_glXQueryExtensionsString(void) +{ return ""; } - -static const char *STANDARD_GL_FUNCTIONS ={ +static const char *STANDARD_GL_FUNCTIONS = { /* Miscellaneous */ -"glClearIndex\0" -"glClearColor\0" -"glClear\0" -"glIndexMask\0" -"glColorMask\0" -"glAlphaFunc\0" -"glBlendFunc\0" -"glLogicOp\0" -"glCullFace\0" -"glFrontFace\0" -"glPointSize\0" -"glLineWidth\0" -"glLineStipple\0" -"glPolygonMode\0" -"glPolygonOffset\0" -"glPolygonStipple\0" -"glGetPolygonStipple\0" -"glEdgeFlag\0" -"glEdgeFlagv\0" -"glScissor\0" -"glClipPlane\0" -"glGetClipPlane\0" -"glDrawBuffer\0" -"glReadBuffer\0" -"glEnable\0" -"glDisable\0" -"glIsEnabled\0" -"glEnableClientState\0" -"glDisableClientState\0" -"glGetBooleanv\0" -"glGetDoublev\0" -"glGetFloatv\0" -"glGetIntegerv\0" -"glPushAttrib\0" -"glPopAttrib\0" -"glPushClientAttrib\0" -"glPopClientAttrib\0" -"glRenderMode\0" -"glGetError\0" -"glGetString\0" -"glFinish\0" -"glFlush\0" -"glHint\0" + "glClearIndex\0" + "glClearColor\0" + "glClear\0" + "glIndexMask\0" + "glColorMask\0" + "glAlphaFunc\0" + "glBlendFunc\0" + "glLogicOp\0" + "glCullFace\0" + "glFrontFace\0" + "glPointSize\0" + "glLineWidth\0" + "glLineStipple\0" + "glPolygonMode\0" + "glPolygonOffset\0" + "glPolygonStipple\0" + "glGetPolygonStipple\0" + "glEdgeFlag\0" + "glEdgeFlagv\0" + "glScissor\0" + "glClipPlane\0" + "glGetClipPlane\0" + "glDrawBuffer\0" + "glReadBuffer\0" + "glEnable\0" + "glDisable\0" + "glIsEnabled\0" + "glEnableClientState\0" + "glDisableClientState\0" + "glGetBooleanv\0" + "glGetDoublev\0" + "glGetFloatv\0" + "glGetIntegerv\0" + "glPushAttrib\0" + "glPopAttrib\0" + "glPushClientAttrib\0" + "glPopClientAttrib\0" + "glRenderMode\0" + "glGetError\0" "glGetString\0" "glFinish\0" "glFlush\0" "glHint\0" /* Depth Buffer */ -"glClearDepth\0" -"glDepthFunc\0" -"glDepthMask\0" -"glDepthRange\0" + "glClearDepth\0" "glDepthFunc\0" "glDepthMask\0" "glDepthRange\0" /* Accumulation Buffer */ -"glClearAccum\0" -"glAccum\0" + "glClearAccum\0" "glAccum\0" /* Transformation */ -"glMatrixMode\0" -"glOrtho\0" -"glFrustum\0" -"glViewport\0" -"glPushMatrix\0" -"glPopMatrix\0" -"glLoadIdentity\0" -"glLoadMatrixd\0" -"glLoadMatrixf\0" -"glMultMatrixd\0" -"glMultMatrixf\0" -"glRotated\0" -"glRotatef\0" -"glScaled\0" -"glScalef\0" -"glTranslated\0" -"glTranslatef\0" + "glMatrixMode\0" + "glOrtho\0" + "glFrustum\0" + "glViewport\0" + "glPushMatrix\0" + "glPopMatrix\0" + "glLoadIdentity\0" + "glLoadMatrixd\0" + "glLoadMatrixf\0" + "glMultMatrixd\0" + "glMultMatrixf\0" + "glRotated\0" + "glRotatef\0" + "glScaled\0" "glScalef\0" "glTranslated\0" "glTranslatef\0" /* Display Lists */ -"glIsList\0" -"glDeleteLists\0" -"glGenLists\0" -"glNewList\0" -"glEndList\0" -"glCallList\0" -"glCallLists\0" -"glListBase\0" + "glIsList\0" + "glDeleteLists\0" + "glGenLists\0" + "glNewList\0" + "glEndList\0" "glCallList\0" "glCallLists\0" "glListBase\0" /* Drawing Functions */ -"glBegin\0" -"glEnd\0" -"glVertex2d\0" -"glVertex2f\0" -"glVertex2i\0" -"glVertex2s\0" -"glVertex3d\0" -"glVertex3f\0" -"glVertex3i\0" -"glVertex3s\0" -"glVertex4d\0" -"glVertex4f\0" -"glVertex4i\0" -"glVertex4s\0" -"glVertex2dv\0" -"glVertex2fv\0" -"glVertex2iv\0" -"glVertex2sv\0" -"glVertex3dv\0" -"glVertex3fv\0" -"glVertex3iv\0" -"glVertex3sv\0" -"glVertex4dv\0" -"glVertex4fv\0" -"glVertex4iv\0" -"glVertex4sv\0" -"glNormal3b\0" -"glNormal3d\0" -"glNormal3f\0" -"glNormal3i\0" -"glNormal3s\0" -"glNormal3bv\0" -"glNormal3dv\0" -"glNormal3fv\0" -"glNormal3iv\0" -"glNormal3sv\0" -"glIndexd\0" -"glIndexf\0" -"glIndexi\0" -"glIndexs\0" -"glIndexub\0" -"glIndexdv\0" -"glIndexfv\0" -"glIndexiv\0" -"glIndexsv\0" -"glIndexubv\0" -"glColor3b\0" -"glColor3d\0" -"glColor3f\0" -"glColor3i\0" -"glColor3s\0" -"glColor3ub\0" -"glColor3ui\0" -"glColor3us\0" -"glColor4b\0" -"glColor4d\0" -"glColor4f\0" -"glColor4i\0" -"glColor4s\0" -"glColor4ub\0" -"glColor4ui\0" -"glColor4us\0" -"glColor3bv\0" -"glColor3dv\0" -"glColor3fv\0" -"glColor3iv\0" -"glColor3sv\0" -"glColor3ubv\0" -"glColor3uiv\0" -"glColor3usv\0" -"glColor4bv\0" -"glColor4dv\0" -"glColor4fv\0" -"glColor4iv\0" -"glColor4sv\0" -"glColor4ubv\0" -"glColor4uiv\0" -"glColor4usv\0" -"glTexCoord1d\0" -"glTexCoord1f\0" -"glTexCoord1i\0" -"glTexCoord1s\0" -"glTexCoord2d\0" -"glTexCoord2f\0" -"glTexCoord2i\0" -"glTexCoord2s\0" -"glTexCoord3d\0" -"glTexCoord3f\0" -"glTexCoord3i\0" -"glTexCoord3s\0" -"glTexCoord4d\0" -"glTexCoord4f\0" -"glTexCoord4i\0" -"glTexCoord4s\0" -"glTexCoord1dv\0" -"glTexCoord1fv\0" -"glTexCoord1iv\0" -"glTexCoord1sv\0" -"glTexCoord2dv\0" -"glTexCoord2fv\0" -"glTexCoord2iv\0" -"glTexCoord2sv\0" -"glTexCoord3dv\0" -"glTexCoord3fv\0" -"glTexCoord3iv\0" -"glTexCoord3sv\0" -"glTexCoord4dv\0" -"glTexCoord4fv\0" -"glTexCoord4iv\0" -"glTexCoord4sv\0" -"glRasterPos2d\0" -"glRasterPos2f\0" -"glRasterPos2i\0" -"glRasterPos2s\0" -"glRasterPos3d\0" -"glRasterPos3f\0" -"glRasterPos3i\0" -"glRasterPos3s\0" -"glRasterPos4d\0" -"glRasterPos4f\0" -"glRasterPos4i\0" -"glRasterPos4s\0" -"glRasterPos2dv\0" -"glRasterPos2fv\0" -"glRasterPos2iv\0" -"glRasterPos2sv\0" -"glRasterPos3dv\0" -"glRasterPos3fv\0" -"glRasterPos3iv\0" -"glRasterPos3sv\0" -"glRasterPos4dv\0" -"glRasterPos4fv\0" -"glRasterPos4iv\0" -"glRasterPos4sv\0" -"glRectd\0" -"glRectf\0" -"glRecti\0" -"glRects\0" -"glRectdv\0" -"glRectfv\0" -"glRectiv\0" -"glRectsv\0" + "glBegin\0" + "glEnd\0" + "glVertex2d\0" + "glVertex2f\0" + "glVertex2i\0" + "glVertex2s\0" + "glVertex3d\0" + "glVertex3f\0" + "glVertex3i\0" + "glVertex3s\0" + "glVertex4d\0" + "glVertex4f\0" + "glVertex4i\0" + "glVertex4s\0" + "glVertex2dv\0" + "glVertex2fv\0" + "glVertex2iv\0" + "glVertex2sv\0" + "glVertex3dv\0" + "glVertex3fv\0" + "glVertex3iv\0" + "glVertex3sv\0" + "glVertex4dv\0" + "glVertex4fv\0" + "glVertex4iv\0" + "glVertex4sv\0" + "glNormal3b\0" + "glNormal3d\0" + "glNormal3f\0" + "glNormal3i\0" + "glNormal3s\0" + "glNormal3bv\0" + "glNormal3dv\0" + "glNormal3fv\0" + "glNormal3iv\0" + "glNormal3sv\0" + "glIndexd\0" + "glIndexf\0" + "glIndexi\0" + "glIndexs\0" + "glIndexub\0" + "glIndexdv\0" + "glIndexfv\0" + "glIndexiv\0" + "glIndexsv\0" + "glIndexubv\0" + "glColor3b\0" + "glColor3d\0" + "glColor3f\0" + "glColor3i\0" + "glColor3s\0" + "glColor3ub\0" + "glColor3ui\0" + "glColor3us\0" + "glColor4b\0" + "glColor4d\0" + "glColor4f\0" + "glColor4i\0" + "glColor4s\0" + "glColor4ub\0" + "glColor4ui\0" + "glColor4us\0" + "glColor3bv\0" + "glColor3dv\0" + "glColor3fv\0" + "glColor3iv\0" + "glColor3sv\0" + "glColor3ubv\0" + "glColor3uiv\0" + "glColor3usv\0" + "glColor4bv\0" + "glColor4dv\0" + "glColor4fv\0" + "glColor4iv\0" + "glColor4sv\0" + "glColor4ubv\0" + "glColor4uiv\0" + "glColor4usv\0" + "glTexCoord1d\0" + "glTexCoord1f\0" + "glTexCoord1i\0" + "glTexCoord1s\0" + "glTexCoord2d\0" + "glTexCoord2f\0" + "glTexCoord2i\0" + "glTexCoord2s\0" + "glTexCoord3d\0" + "glTexCoord3f\0" + "glTexCoord3i\0" + "glTexCoord3s\0" + "glTexCoord4d\0" + "glTexCoord4f\0" + "glTexCoord4i\0" + "glTexCoord4s\0" + "glTexCoord1dv\0" + "glTexCoord1fv\0" + "glTexCoord1iv\0" + "glTexCoord1sv\0" + "glTexCoord2dv\0" + "glTexCoord2fv\0" + "glTexCoord2iv\0" + "glTexCoord2sv\0" + "glTexCoord3dv\0" + "glTexCoord3fv\0" + "glTexCoord3iv\0" + "glTexCoord3sv\0" + "glTexCoord4dv\0" + "glTexCoord4fv\0" + "glTexCoord4iv\0" + "glTexCoord4sv\0" + "glRasterPos2d\0" + "glRasterPos2f\0" + "glRasterPos2i\0" + "glRasterPos2s\0" + "glRasterPos3d\0" + "glRasterPos3f\0" + "glRasterPos3i\0" + "glRasterPos3s\0" + "glRasterPos4d\0" + "glRasterPos4f\0" + "glRasterPos4i\0" + "glRasterPos4s\0" + "glRasterPos2dv\0" + "glRasterPos2fv\0" + "glRasterPos2iv\0" + "glRasterPos2sv\0" + "glRasterPos3dv\0" + "glRasterPos3fv\0" + "glRasterPos3iv\0" + "glRasterPos3sv\0" + "glRasterPos4dv\0" + "glRasterPos4fv\0" + "glRasterPos4iv\0" + "glRasterPos4sv\0" + "glRectd\0" + "glRectf\0" + "glRecti\0" + "glRects\0" "glRectdv\0" "glRectfv\0" "glRectiv\0" "glRectsv\0" /* Lighting */ -"glShadeModel\0" -"glLightf\0" -"glLighti\0" -"glLightfv\0" -"glLightiv\0" -"glGetLightfv\0" -"glGetLightiv\0" -"glLightModelf\0" -"glLightModeli\0" -"glLightModelfv\0" -"glLightModeliv\0" -"glMaterialf\0" -"glMateriali\0" -"glMaterialfv\0" -"glMaterialiv\0" -"glGetMaterialfv\0" -"glGetMaterialiv\0" -"glColorMaterial\0" + "glShadeModel\0" + "glLightf\0" + "glLighti\0" + "glLightfv\0" + "glLightiv\0" + "glGetLightfv\0" + "glGetLightiv\0" + "glLightModelf\0" + "glLightModeli\0" + "glLightModelfv\0" + "glLightModeliv\0" + "glMaterialf\0" + "glMateriali\0" + "glMaterialfv\0" + "glMaterialiv\0" + "glGetMaterialfv\0" "glGetMaterialiv\0" "glColorMaterial\0" /* Raster functions */ -"glPixelZoom\0" -"glPixelStoref\0" -"glPixelStorei\0" -"glPixelTransferf\0" -"glPixelTransferi\0" -"glPixelMapfv\0" -"glPixelMapuiv\0" -"glPixelMapusv\0" -"glGetPixelMapfv\0" -"glGetPixelMapuiv\0" -"glGetPixelMapusv\0" -"glBitmap\0" -"glReadPixels\0" -"glDrawPixels\0" -"glCopyPixels\0" + "glPixelZoom\0" + "glPixelStoref\0" + "glPixelStorei\0" + "glPixelTransferf\0" + "glPixelTransferi\0" + "glPixelMapfv\0" + "glPixelMapuiv\0" + "glPixelMapusv\0" + "glGetPixelMapfv\0" + "glGetPixelMapuiv\0" + "glGetPixelMapusv\0" + "glBitmap\0" "glReadPixels\0" "glDrawPixels\0" "glCopyPixels\0" /* Stenciling */ -"glStencilFunc\0" -"glStencilMask\0" -"glStencilOp\0" -"glClearStencil\0" + "glStencilFunc\0" "glStencilMask\0" "glStencilOp\0" "glClearStencil\0" /* Texture mapping */ -"glTexGend\0" -"glTexGenf\0" -"glTexGeni\0" -"glTexGendv\0" -"glTexGenfv\0" -"glTexGeniv\0" -"glGetTexGendv\0" -"glGetTexGenfv\0" -"glGetTexGeniv\0" -"glTexEnvf\0" -"glTexEnvi\0" -"glTexEnvfv\0" -"glTexEnviv\0" -"glGetTexEnvfv\0" -"glGetTexEnviv\0" -"glTexParameterf\0" -"glTexParameteri\0" -"glTexParameterfv\0" -"glTexParameteriv\0" -"glGetTexParameterfv\0" -"glGetTexParameteriv\0" -"glGetTexLevelParameterfv\0" -"glGetTexLevelParameteriv\0" -"glTexImage1D\0" -"glTexImage2D\0" -"glGetTexImage\0" + "glTexGend\0" + "glTexGenf\0" + "glTexGeni\0" + "glTexGendv\0" + "glTexGenfv\0" + "glTexGeniv\0" + "glGetTexGendv\0" + "glGetTexGenfv\0" + "glGetTexGeniv\0" + "glTexEnvf\0" + "glTexEnvi\0" + "glTexEnvfv\0" + "glTexEnviv\0" + "glGetTexEnvfv\0" + "glGetTexEnviv\0" + "glTexParameterf\0" + "glTexParameteri\0" + "glTexParameterfv\0" + "glTexParameteriv\0" + "glGetTexParameterfv\0" + "glGetTexParameteriv\0" + "glGetTexLevelParameterfv\0" + "glGetTexLevelParameteriv\0" + "glTexImage1D\0" "glTexImage2D\0" "glGetTexImage\0" /* Evaluators */ -"glMap1d\0" -"glMap1f\0" -"glMap2d\0" -"glMap2f\0" -"glGetMapdv\0" -"glGetMapfv\0" -"glGetMapiv\0" -"glEvalCoord1d\0" -"glEvalCoord1f\0" -"glEvalCoord1dv\0" -"glEvalCoord1fv\0" -"glEvalCoord2d\0" -"glEvalCoord2f\0" -"glEvalCoord2dv\0" -"glEvalCoord2fv\0" -"glMapGrid1d\0" -"glMapGrid1f\0" -"glMapGrid2d\0" -"glMapGrid2f\0" -"glEvalPoint1\0" -"glEvalPoint2\0" -"glEvalMesh1\0" -"glEvalMesh2\0" + "glMap1d\0" + "glMap1f\0" + "glMap2d\0" + "glMap2f\0" + "glGetMapdv\0" + "glGetMapfv\0" + "glGetMapiv\0" + "glEvalCoord1d\0" + "glEvalCoord1f\0" + "glEvalCoord1dv\0" + "glEvalCoord1fv\0" + "glEvalCoord2d\0" + "glEvalCoord2f\0" + "glEvalCoord2dv\0" + "glEvalCoord2fv\0" + "glMapGrid1d\0" + "glMapGrid1f\0" + "glMapGrid2d\0" + "glMapGrid2f\0" + "glEvalPoint1\0" "glEvalPoint2\0" "glEvalMesh1\0" "glEvalMesh2\0" /* Fog */ -"glFogf\0" -"glFogi\0" -"glFogfv\0" -"glFogiv\0" + "glFogf\0" "glFogi\0" "glFogfv\0" "glFogiv\0" /* Selection and Feedback */ -"glFeedbackBuffer\0" -"glPassThrough\0" -"glSelectBuffer\0" -"glInitNames\0" -"glLoadName\0" -"glPushName\0" -"glPopName\0" + "glFeedbackBuffer\0" + "glPassThrough\0" + "glSelectBuffer\0" + "glInitNames\0" "glLoadName\0" "glPushName\0" "glPopName\0" /* 1.1 functions */ /* texture objects */ -"glGenTextures\0" -"glDeleteTextures\0" -"glBindTexture\0" -"glPrioritizeTextures\0" -"glAreTexturesResident\0" -"glIsTexture\0" + "glGenTextures\0" + "glDeleteTextures\0" + "glBindTexture\0" + "glPrioritizeTextures\0" "glAreTexturesResident\0" "glIsTexture\0" /* texture mapping */ -"glTexSubImage1D\0" -"glTexSubImage2D\0" -"glCopyTexImage1D\0" -"glCopyTexImage2D\0" -"glCopyTexSubImage1D\0" -"glCopyTexSubImage2D\0" + "glTexSubImage1D\0" + "glTexSubImage2D\0" + "glCopyTexImage1D\0" + "glCopyTexImage2D\0" "glCopyTexSubImage1D\0" "glCopyTexSubImage2D\0" /* vertex arrays */ -"glVertexPointer\0" -"glNormalPointer\0" -"glColorPointer\0" -"glIndexPointer\0" -"glTexCoordPointer\0" -"glEdgeFlagPointer\0" -"glGetPointerv\0" -"glArrayElement\0" -"glDrawArrays\0" -"glDrawElements\0" -"glInterleavedArrays\0" + "glVertexPointer\0" + "glNormalPointer\0" + "glColorPointer\0" + "glIndexPointer\0" + "glTexCoordPointer\0" + "glEdgeFlagPointer\0" + "glGetPointerv\0" + "glArrayElement\0" + "glDrawArrays\0" "glDrawElements\0" "glInterleavedArrays\0" /* GLX */ -"glXChooseVisual\0" -"glXQueryExtensionsString\0" -"glXQueryServerString\0" -"glXGetClientString\0" -"glXCreateContext\0" -"glXCreateNewContext\0" -"glXCopyContext\0" -"glXDestroyContext\0" -"glXQueryVersion\0" -"glXMakeCurrent\0" -"glXSwapBuffers\0" -"glXGetConfig\0" -"glXQueryExtension\0" -"glXChooseFBConfig\0" -"glXGetFBConfigs\0" -"glXGetFBConfigAttrib\0" -"glXQueryContext\0" -"glXQueryDrawable\0" -"glXGetVisualFromFBConfig\0" -"glXIsDirect\0" -"glXCreatePixmap\0" -"glXDestroyPixmap\0" -"glXCreatePbuffer\0" -"glXDestroyPbuffer\0" -"\0" + "glXChooseVisual\0" + "glXQueryExtensionsString\0" + "glXQueryServerString\0" + "glXGetClientString\0" + "glXCreateContext\0" + "glXCreateNewContext\0" + "glXCopyContext\0" + "glXDestroyContext\0" + "glXQueryVersion\0" + "glXMakeCurrent\0" + "glXSwapBuffers\0" + "glXGetConfig\0" + "glXQueryExtension\0" + "glXChooseFBConfig\0" + "glXGetFBConfigs\0" + "glXGetFBConfigAttrib\0" + "glXQueryContext\0" + "glXQueryDrawable\0" + "glXGetVisualFromFBConfig\0" + "glXIsDirect\0" + "glXCreatePixmap\0" + "glXDestroyPixmap\0" "glXCreatePbuffer\0" "glXDestroyPbuffer\0" "\0" }; /* Like wglGetProcAddress/glxGetProcAddress */ -void *glo_getprocaddress(const char *procName) { +void *glo_getprocaddress(const char *procName) +{ HGLRC oldCtx; HDC oldDC; if (!glo_inited) @@ -680,175 +647,179 @@ void *glo_getprocaddress(const char *procName) { oldCtx = wglGetCurrentContext(); oldDC = wglGetCurrentDC(); - if (oldDC!=glo.hDC || oldCtx!=glo.hContext) + if (oldDC != glo.hDC || oldCtx != glo.hContext) wglMakeCurrent(glo.hDC, glo.hContext); void *procAddr = wglGetProcAddress(procName); - if (oldDC!=glo.hDC || oldCtx!=glo.hContext) + if (oldDC != glo.hDC || oldCtx != glo.hContext) wglMakeCurrent(oldDC, oldCtx); /* wgl doesn't know about the glx functions - but - we never call these anyway (they're implemented in - opengl_exec), so all we need to do is return a nunzero value... - - But we also have to check for 'standard' GL function names - too as wgl doesn't return those either! */ - /* Caller in opengl_exec.c may query some base GL API, then call them - * directly. On windows, wglGetProcAddress usually return NULL in such - * case, then we return 1, which casue segfault when accessing (void*)1. We - * should call base GL API directly instead of GET_EXT_PTR + ptr_func_*. - * TODO: add LoadLibrary + GetProcAddress as call back. - */ - if (procAddr==0) { + we never call these anyway (they're implemented in + opengl_exec), so all we need to do is return a nunzero value... + + But we also have to check for 'standard' GL function names + too as wgl doesn't return those either! */ + /* Caller in opengl_exec.c may query some base GL API, then call them + * directly. On windows, wglGetProcAddress usually return NULL in such + * case, then we return 1, which casue segfault when accessing (void*)1. We + * should call base GL API directly instead of GET_EXT_PTR + ptr_func_*. + * TODO: add LoadLibrary + GetProcAddress as call back. + */ + if (procAddr == 0) { const char *p = STANDARD_GL_FUNCTIONS; while (*p) { if (!strcmp(procName, p)) { - procAddr = (void*)1; + procAddr = (void *)1; break; } // skip to the next '0' and then just over it - while (*p) p++; + while (*p) + p++; p++; } } /*printf("wglGetProcAddress '%s' -> %p\n", procName, procAddr); - fflush(stdout);*/ + fflush(stdout); */ return procAddr; } -void glo_surface_updatecontents(GloSurface *surface) { - /* NOT IMPLEMENTED YET. */ - printf("glo_surface_updatecontents() is not implemented for windows. \n"); + +void glo_surface_updatecontents(GloSurface * surface) +{ + /* NOT IMPLEMENTED YET. */ + printf("glo_surface_updatecontents() is not implemented for windows. \n"); } /* ------------------------------------------------------------------------ */ /* Create a light-weight context just for creating surface */ -GloContext *__glo_context_create(int formatFlags) { +GloContext *__glo_context_create(int formatFlags) +{ GloContext *context; // pixel format attributes - int pf_attri[2*MAX_ATTRIBS]; - float pf_attrf[] = {0, 0}; + int pf_attri[2 * MAX_ATTRIBS]; + float pf_attrf[] = { 0, 0 }; unsigned int numReturned = 0; - int pb_attr[] = { 0 }; - int rgbaBits[4]; - int index = 0; - - /*Initlized array because it needs to be terminated by 0*/ - for(index = 0; index < 2*MAX_ATTRIBS; index ++) - pf_attri[index] = 0; - - index = 0; - pf_attri[2*index] = WGL_SUPPORT_OPENGL_ARB; - pf_attri[2*index +1 ] = TRUE; - index ++; - - pf_attri[2*index] = WGL_DRAW_TO_PBUFFER_ARB; - pf_attri[2*index +1 ] = TRUE; - index ++; - - pf_attri[2*index] = WGL_RED_BITS_ARB; - pf_attri[2*index +1 ] = 8; - index ++; - - pf_attri[2*index] = WGL_GREEN_BITS_ARB; - pf_attri[2*index +1 ] = 8; - index ++; - - pf_attri[2*index] = WGL_BLUE_BITS_ARB; - pf_attri[2*index +1 ] = 8; - index ++; - - pf_attri[2*index] = WGL_ALPHA_BITS_ARB; - pf_attri[2*index +1 ] = 8; - index ++; - - pf_attri[2*index] = WGL_DEPTH_BITS_ARB; - pf_attri[2*index +1 ] = 0; - index ++; - - pf_attri[2*index] = WGL_STENCIL_BITS_ARB; - pf_attri[2*index +1 ] = 0; - index ++; - - pf_attri[2*index] = WGL_DOUBLE_BUFFER_ARB; - pf_attri[2*index +1 ] = FALSE; - index ++; - - if(Render_texture_support) - { - fprintf(stdout, "Render to texture supported, add attributes in array!\n"); - pf_attri[2*index] = WGL_DRAW_TO_PBUFFER_ARB; - pf_attri[2*index +1 ] = TRUE; - index ++; - - pf_attri[2*index] = WGL_BIND_TO_TEXTURE_RGBA_ARB; - pf_attri[2*index +1 ] = TRUE; - - } else { - fprintf(stderr, "Render to Texture not supported, disable attributes in array!\n"); - } - - + int pb_attr[] = { 0 }; + int rgbaBits[4]; + int index = 0; + + /*Initlized array because it needs to be terminated by 0 */ + for (index = 0; index < 2 * MAX_ATTRIBS; index++) + pf_attri[index] = 0; + + index = 0; + pf_attri[2 * index] = WGL_SUPPORT_OPENGL_ARB; + pf_attri[2 * index + 1] = TRUE; + index++; + + pf_attri[2 * index] = WGL_DRAW_TO_PBUFFER_ARB; + pf_attri[2 * index + 1] = TRUE; + index++; + + pf_attri[2 * index] = WGL_RED_BITS_ARB; + pf_attri[2 * index + 1] = 8; + index++; + + pf_attri[2 * index] = WGL_GREEN_BITS_ARB; + pf_attri[2 * index + 1] = 8; + index++; + + pf_attri[2 * index] = WGL_BLUE_BITS_ARB; + pf_attri[2 * index + 1] = 8; + index++; + + pf_attri[2 * index] = WGL_ALPHA_BITS_ARB; + pf_attri[2 * index + 1] = 8; + index++; + + pf_attri[2 * index] = WGL_DEPTH_BITS_ARB; + pf_attri[2 * index + 1] = 0; + index++; + + pf_attri[2 * index] = WGL_STENCIL_BITS_ARB; + pf_attri[2 * index + 1] = 0; + index++; + + pf_attri[2 * index] = WGL_DOUBLE_BUFFER_ARB; + pf_attri[2 * index + 1] = FALSE; + index++; + + if (Render_texture_support) { + fprintf(stdout, + "Render to texture supported, add attributes in array!\n"); + pf_attri[2 * index] = WGL_DRAW_TO_PBUFFER_ARB; + pf_attri[2 * index + 1] = TRUE; + index++; + + pf_attri[2 * index] = WGL_BIND_TO_TEXTURE_RGBA_ARB; + pf_attri[2 * index + 1] = TRUE; + + } else { + fprintf(stderr, + "Render to Texture not supported, disable attributes in array!\n"); + } if (!glo_inited) glo_init(); - context = (GloContext*)malloc(sizeof(GloContext)); + context = (GloContext *) malloc(sizeof(GloContext)); memset(context, 0, sizeof(GloContext)); context->formatFlags = formatFlags; // set up the surface format from the flags we were given glo_flags_get_rgba_bits(context->formatFlags, rgbaBits); - pf_attri[5] = rgbaBits[0]; - pf_attri[7] = rgbaBits[1]; - pf_attri[9] = rgbaBits[2]; + pf_attri[5] = rgbaBits[0]; + pf_attri[7] = rgbaBits[1]; + pf_attri[9] = rgbaBits[2]; pf_attri[11] = rgbaBits[3]; pf_attri[13] = glo_flags_get_depth_bits(context->formatFlags); pf_attri[15] = glo_flags_get_stencil_bits(context->formatFlags); // find out what pixel format to use - wglChoosePixelFormatARB( glo.hDC, pf_attri, pf_attrf, 1, &context->wglPixelFormat, &numReturned); - if( numReturned == 0 ) { - printf( "No matching configs found.\n" ); + wglChoosePixelFormatARB(glo.hDC, pf_attri, pf_attrf, 1, + &context->wglPixelFormat, &numReturned); + if (numReturned == 0) { + printf("No matching configs found.\n"); //exit( EXIT_FAILURE ); - return NULL; + return NULL; } - // We create a tiny pbuffer - just so we can make a context of the right pixel format - context->hPBuffer = wglCreatePbufferARB( glo.hDC, context->wglPixelFormat, - 16, 16, pb_attr ); - if( !context->hPBuffer ) { - printf( "Couldn't create the PBuffer\n" ); + context->hPBuffer = wglCreatePbufferARB(glo.hDC, context->wglPixelFormat, + 16, 16, pb_attr); + if (!context->hPBuffer) { + printf("Couldn't create the PBuffer\n"); //exit( EXIT_FAILURE ); - return NULL; + return NULL; } - context->hDC = wglGetPbufferDCARB( context->hPBuffer ); - if( !context->hDC ) { - printf( "Couldn't create the DC\n" ); + context->hDC = wglGetPbufferDCARB(context->hPBuffer); + if (!context->hDC) { + printf("Couldn't create the DC\n"); //exit( EXIT_FAILURE ); - return NULL; + return NULL; } - return context; + return context; } /* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */ -GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { +GloContext *glo_context_create(int formatFlags, GloContext * shareLists) +{ GloContext *context = __glo_context_create(formatFlags); - if (!context) { - return NULL; - } + if (!context) { + return NULL; + } context->hContext = wglCreateContext(context->hDC); if (context->hContext == NULL) { - printf( "Unable to create GL context\n" ); + printf("Unable to create GL context\n"); //exit( EXIT_FAILURE ); - return NULL; + return NULL; } if (shareLists) { @@ -860,8 +831,10 @@ GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { } /* Destroy a previouslu created OpenGL context */ -void glo_context_destroy(GloContext *context) { - if (!context) return; +void glo_context_destroy(GloContext * context) +{ + if (!context) + return; if (context->hContext) { wglDeleteContext(context->hContext); @@ -872,15 +845,15 @@ void glo_context_destroy(GloContext *context) { /* ------------------------------------------------------------------------ */ /* Update the context in surface and handle previous context */ -void glo_surface_update_context(GloSurface *surface, GloContext *context, int free_flags) +void glo_surface_update_context(GloSurface * surface, GloContext * context, + int free_flags) { /* If previous context is light-weight context, just free it. If previous * context is valid one binded with surface via MakeCurrent, we need unbind * from original glstate */ - if ( surface->context ) - { - if ( free_flags ) /* light-weight context */ + if (surface->context) { + if (free_flags) /* light-weight context */ g_free(surface->context); } surface->context = context; @@ -888,75 +861,83 @@ void glo_surface_update_context(GloSurface *surface, GloContext *context, int fr /* Create a surface with given width and height, formatflags are from the * GLO_ constants */ -GloSurface *glo_surface_create(int width, int height, GloContext *context) { - GloSurface *surface; - int pb_attr[] = { +GloSurface *glo_surface_create(int width, int height, GloContext * context) +{ + GloSurface *surface; + int pb_attr[] = { /* Need following 2 to support surface as texture */ - WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB, - WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, + WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB, + WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, 0 }; - + // Create the p-buffer... - surface = (GloSurface*)malloc(sizeof(GloSurface)); + surface = (GloSurface *) malloc(sizeof(GloSurface)); memset(surface, 0, sizeof(GloSurface)); surface->width = width; surface->height = height; surface->context = context; - surface->hPBuffer = wglCreatePbufferARB( glo.hDC, context->wglPixelFormat, - surface->width, surface->height, pb_attr ); - if( !surface->hPBuffer ) { - printf( "Couldn't create the PBuffer\n" ); + surface->hPBuffer = wglCreatePbufferARB(glo.hDC, context->wglPixelFormat, + surface->width, surface->height, + pb_attr); + if (!surface->hPBuffer) { + printf("Couldn't create the PBuffer\n"); //exit( EXIT_FAILURE ); - return NULL; + return NULL; } - surface->hDC = wglGetPbufferDCARB( surface->hPBuffer ); - if( !surface->hDC ) { - printf( "Couldn't create the DC\n" ); + surface->hDC = wglGetPbufferDCARB(surface->hPBuffer); + if (!surface->hDC) { + printf("Couldn't create the DC\n"); //exit( EXIT_FAILURE ); - return NULL; + return NULL; } return surface; } /* Destroy the given surface */ -void glo_surface_destroy(GloSurface *surface) { - if (!surface) return; +void glo_surface_destroy(GloSurface * surface) +{ + if (!surface) + return; - if( surface->hPBuffer != NULL ) { - wglReleasePbufferDCARB( surface->hPBuffer, surface->hDC ); - wglDestroyPbufferARB( surface->hPBuffer ); + if (surface->hPBuffer != NULL) { + wglReleasePbufferDCARB(surface->hPBuffer, surface->hDC); + wglDestroyPbufferARB(surface->hPBuffer); } - if( surface->hDC != NULL ) { - ReleaseDC( glo.hWnd, surface->hDC ); + if (surface->hDC != NULL) { + ReleaseDC(glo.hWnd, surface->hDC); } free(surface); } /* Make the given surface current */ -int glo_surface_makecurrent(GloSurface *surface) { - if (surface) { - return wglMakeCurrent( surface->hDC, surface->context->hContext ); - } else { - return wglMakeCurrent( NULL, NULL ); - } +int glo_surface_makecurrent(GloSurface * surface) +{ + if (surface) { + return wglMakeCurrent(surface->hDC, surface->context->hContext); + } else { + return wglMakeCurrent(NULL, NULL); + } } /* Get the contents of the given surface */ -void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, void *data) { - - if (!surface) - return; - // Compatible / fallback method. - glo_surface_getcontents_readpixels(surface->context->formatFlags, - stride, bpp, surface->width, - surface->height, data, 0); +void glo_surface_getcontents(GloSurface * surface, int stride, int bpp, + void *data) +{ + + if (!surface) + return; + // Compatible / fallback method. + glo_surface_getcontents_readpixels(surface->context->formatFlags, + stride, bpp, surface->width, + surface->height, data, 0); } /* Return the width and height of the given surface */ -void glo_surface_get_size(GloSurface *surface, int *width, int *height) { +void glo_surface_get_size(GloSurface * surface, int *width, int *height) +{ if (width) *width = surface->width; if (height) @@ -964,7 +945,8 @@ void glo_surface_get_size(GloSurface *surface, int *width, int *height) { } /* Bind the surface as texture */ -void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface, int surface_type) +void glo_surface_as_texture(GloContext * ctxt, GloSurface * surface, + int surface_type) { int glFormat, glType; int bpp = 4; @@ -982,32 +964,34 @@ void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface, int surface_t oldDC = wglGetCurrentDC(); glo_surface_makecurrent(surface); glo_surface_updatecontents(surface); - glo_flags_get_readpixel_type(surface->context->formatFlags, &glFormat, &glType); + glo_flags_get_readpixel_type(surface->context->formatFlags, &glFormat, + &glType); // Make sure we do not flip pbuffer surfaces on Windows glo_surface_getcontents_readpixels(surface->context->formatFlags, - stride, bpp *8, surface->width, - surface->height, data, (surface_type == SURFACE_PBUFFER)); + stride, bpp * 8, surface->width, + surface->height, data, + (surface_type == SURFACE_PBUFFER)); /* Restore previous context for setting texture */ wglMakeCurrent(oldDC, oldCtx); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, glFormat, glType, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, + glFormat, glType, data); free(data); } -void glo_surface_release_texture(GloSurface *surface) +void glo_surface_release_texture(GloSurface * surface) { - if(!Render_texture_support) - return ; + if (!Render_texture_support) + return; - if (!wglReleaseTexImageARB) - { - fprintf (stderr, "wglReleaseTexImageARB not supported! Can't emulate glEGLImageTargetTexture2DOES!\n"); + if (!wglReleaseTexImageARB) { + fprintf(stderr, + "wglReleaseTexImageARB not supported! Can't emulate glEGLImageTargetTexture2DOES!\n"); return; } - if ( !wglReleaseTexImageARB(surface->hPBuffer, WGL_FRONT_LEFT_ARB) ) - { + if (!wglReleaseTexImageARB(surface->hPBuffer, WGL_FRONT_LEFT_ARB)) { fprintf(stderr, "wglBindTexImageARBr error=%d.\n", glGetError()); } diff --git a/tizen/src/hw/gloffscreen_xcomposite.c b/tizen/src/hw/gloffscreen_xcomposite.c index 14123e9724..aa2838265b 100644 --- a/tizen/src/hw/gloffscreen_xcomposite.c +++ b/tizen/src/hw/gloffscreen_xcomposite.c @@ -44,7 +44,7 @@ #include "gl_mangled.h" #endif -enum{ +enum { SURFACE_WINDOW, SURFACE_PIXMAP, SURFACE_PBUFFER, @@ -62,33 +62,35 @@ struct GloMain glo; int glo_inited = 0; struct _GloContext { - GLuint formatFlags; + GLuint formatFlags; - GLXFBConfig fbConfig; - GLXContext context; + GLXFBConfig fbConfig; + GLXContext context; }; struct _GloSurface { - GLuint width; - GLuint height; + GLuint width; + GLuint height; - GloContext *context; - Window window; + GloContext *context; + Window window; // For use by the 'fast' copy code. - Pixmap pixmap; - XImage *image; - XShmSegmentInfo shminfo; - GLXPixmap glxPixmap; + Pixmap pixmap; + XImage *image; + XShmSegmentInfo shminfo; + GLXPixmap glxPixmap; }; extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, - int bpp, int width, int height, void *data, int noflip); + int bpp, int width, int height, + void *data, int noflip); static void glo_test_readback_methods(void); /* ------------------------------------------------------------------------ */ -int glo_initialised(void) { +int glo_initialised(void) +{ return glo_inited; } @@ -100,76 +102,82 @@ int glo_initialised(void) { * so it is reasonable to redirect error handler here. * */ -static int x_errhandler(Display *dpy, XErrorEvent *e) +static int x_errhandler(Display * dpy, XErrorEvent * e) { //fprintf (stderr, "X Error Happened!\n"); return 0; } +#if 0 /* Sanity test of the host GL capabilities to see whether the gl offscreen * could be well supported */ -int glo_sanity_test (void) { +int glo_sanity_test(void) +{ return 0; } +#endif /* Initialise gloffscreen */ -int glo_init(void) { +int glo_init(void) +{ if (glo_inited) { - printf( "gloffscreen already inited\n" ); + printf("gloffscreen already inited\n"); //exit( EXIT_FAILURE ); - return 1; + return 1; } /* Open a connection to the X server */ - glo.dpy = XOpenDisplay( NULL ); - if ( glo.dpy == NULL ) { - printf( "Unable to open a connection to the X server\n" ); + glo.dpy = XOpenDisplay(NULL); + if (glo.dpy == NULL) { + printf("Unable to open a connection to the X server\n"); //exit( EXIT_FAILURE ); - return 1; + return 1; } - glo_inited = 1; // safe because we are single threaded. Otherwise we cause - // recursion on the next call. + glo_inited = 1; // safe because we are single threaded. Otherwise we cause + // recursion on the next call. // set the X error handler. - XSetErrorHandler (x_errhandler); + XSetErrorHandler(x_errhandler); glo_test_readback_methods(); - return 0; + return 0; } /* Uninitialise gloffscreen */ -void glo_kill(void) { +void glo_kill(void) +{ XCloseDisplay(glo.dpy); glo.dpy = NULL; } - /* Like wglGetProcAddress/glxGetProcAddress */ -void *glo_getprocaddress(const char *procName) { +void *glo_getprocaddress(const char *procName) +{ if (!glo_inited) glo_init(); - return glXGetProcAddressARB((const GLubyte *) procName); + return glXGetProcAddressARB((const GLubyte *)procName); } /* ------------------------------------------------------------------------ */ /* Create a light-weight context just for creating surface */ -GloContext *__glo_context_create(int formatFlags) { +GloContext *__glo_context_create(int formatFlags) +{ - GLXFBConfig *fbConfigs; - int numReturned; - GloContext *context; - int rgbaBits[4]; - int bufferAttributes[] = { + GLXFBConfig *fbConfigs; + int numReturned; + GloContext *context; + int rgbaBits[4]; + int bufferAttributes[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 0, - GLX_STENCIL_SIZE, 0, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 0, + GLX_STENCIL_SIZE, 0, None }; @@ -178,64 +186,68 @@ GloContext *__glo_context_create(int formatFlags) { // set up the surface format from the flags we were given glo_flags_get_rgba_bits(formatFlags, rgbaBits); - bufferAttributes[5] = rgbaBits[0]; - bufferAttributes[7] = rgbaBits[1]; - bufferAttributes[9] = rgbaBits[2]; + bufferAttributes[5] = rgbaBits[0]; + bufferAttributes[7] = rgbaBits[1]; + bufferAttributes[9] = rgbaBits[2]; bufferAttributes[11] = rgbaBits[3]; bufferAttributes[13] = glo_flags_get_depth_bits(formatFlags); bufferAttributes[15] = glo_flags_get_stencil_bits(formatFlags); - fbConfigs = glXChooseFBConfig( glo.dpy, DefaultScreen(glo.dpy), - bufferAttributes, &numReturned ); - if (numReturned==0) { - printf( "No matching configs found.\n" ); + fbConfigs = glXChooseFBConfig(glo.dpy, DefaultScreen(glo.dpy), + bufferAttributes, &numReturned); + if (numReturned == 0) { + printf("No matching configs found.\n"); //exit( EXIT_FAILURE ); - return NULL; + return NULL; } - context = (GloContext*)g_malloc(sizeof(GloContext)); + context = (GloContext *) g_malloc(sizeof(GloContext)); memset(context, 0, sizeof(GloContext)); context->formatFlags = formatFlags; context->fbConfig = fbConfigs[0]; - return context; + return context; } /* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */ -GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { +GloContext *glo_context_create(int formatFlags, GloContext * shareLists) +{ - GloContext *context = __glo_context_create(formatFlags); + GloContext *context = __glo_context_create(formatFlags); - if (!context) { - return NULL; - } + if (!context) { + return NULL; + } /* Create a GLX context for OpenGL rendering */ context->context = glXCreateNewContext(glo.dpy, context->fbConfig, - GLX_RGBA_TYPE, - shareLists ? shareLists->context: NULL, - True ); + GLX_RGBA_TYPE, + shareLists ? shareLists-> + context : NULL, True); if (!context->context) { - printf( "glXCreateNewContext failed\n" ); + printf("glXCreateNewContext failed\n"); //exit( EXIT_FAILURE ); - return NULL; + return NULL; } return context; } /* Destroy a previously created OpenGL context */ -void glo_context_destroy(GloContext *context) { - if (!context) return; +void glo_context_destroy(GloContext * context) +{ + if (!context) + return; // TODO: check for GloSurfaces using this? - glXDestroyContext( glo.dpy, context->context); + glXDestroyContext(glo.dpy, context->context); g_free(context); } -static void glo_surface_free_xshm_image(GloSurface *surface) { +static void glo_surface_free_xshm_image(GloSurface * surface) +{ XShmDetach(glo.dpy, &surface->shminfo); surface->image->data = NULL; XDestroyImage(surface->image); @@ -243,38 +255,46 @@ static void glo_surface_free_xshm_image(GloSurface *surface) { shmctl(surface->shminfo.shmid, IPC_RMID, NULL); } -//FIXMEIM - handle failure to allocate. -static void glo_surface_try_alloc_xshm_image(GloSurface *surface) { - - if(surface->image) +static int glo_surface_try_alloc_xshm_image(GloSurface * surface) +{ + if (surface->image) glo_surface_free_xshm_image(surface); surface->image = XShmCreateImage(glo.dpy, DefaultVisual(glo.dpy, 0), 24, ZPixmap, NULL, &surface->shminfo, surface->width, surface->height); + if (!surface->image) + return -1; surface->shminfo.shmid = shmget(IPC_PRIVATE, surface->image->bytes_per_line * - surface->height, - IPC_CREAT | 0777); + surface->height, IPC_CREAT | 0777); + if (surface->shminfo.shmid < 0) + return -1; + surface->shminfo.shmaddr = shmat(surface->shminfo.shmid, NULL, 0); + if (surface->shminfo.shmaddr == (void *)-1) + return -1; + surface->image->data = surface->shminfo.shmaddr; surface->shminfo.readOnly = False; XShmAttach(glo.dpy, &surface->shminfo); + + return 0; } /* ------------------------------------------------------------------------ */ /* Update the context in surface and handle previous context */ -void glo_surface_update_context(GloSurface *surface, GloContext *context, int free_flags) - { +void glo_surface_update_context(GloSurface * surface, GloContext * context, + int free_flags) +{ /* If previous context is light-weight context, just free it. If previous * context is valid one binded with surface via MakeCurrent, we need unbind * from original glstate */ - if ( surface->context ) - { - if (free_flags) /* light-weight context */ + if (surface->context) { + if (free_flags) /* light-weight context */ g_free(surface->context); } surface->context = context; @@ -282,22 +302,28 @@ void glo_surface_update_context(GloSurface *surface, GloContext *context, int fr /* Create a surface with given width and height, formatflags are from the * GLO_ constants */ -GloSurface *glo_surface_create(int width, int height, GloContext *context) { - GloSurface *surface; +GloSurface *glo_surface_create(int width, int height, GloContext * context) +{ + GloSurface *surface; XSetWindowAttributes attr = { 0 }; unsigned long mask; XVisualInfo *vis; if (!context) - return 0; + return NULL; + + surface = (GloSurface *) g_malloc(sizeof(GloSurface)); + if (!surface) + return NULL; - surface = (GloSurface*)g_malloc(sizeof(GloSurface)); memset(surface, 0, sizeof(GloSurface)); surface->width = width; surface->height = height; surface->context = context; - vis = glXGetVisualFromFBConfig(glo.dpy, ((struct _GloContext*)context)->fbConfig); + vis = + glXGetVisualFromFBConfig(glo.dpy, + ((struct _GloContext *)context)->fbConfig); attr.background_pixel = 0xff000000; attr.border_pixel = 0; @@ -308,41 +334,48 @@ GloSurface *glo_surface_create(int width, int height, GloContext *context) { attr.override_redirect = True; attr.cursor = None; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | - CWOverrideRedirect | CWSaveUnder; + CWOverrideRedirect | CWSaveUnder; - surface->window = XCreateWindow(glo.dpy, DefaultRootWindow(glo.dpy), 0, 3000, width, height, 0, vis->depth, InputOutput, vis->visual, mask, &attr); + surface->window = + XCreateWindow(glo.dpy, DefaultRootWindow(glo.dpy), 0, 3000, width, + height, 0, vis->depth, InputOutput, vis->visual, mask, + &attr); if (!surface->window) { - printf( "XCreateWindow failed\n" ); - //exit( EXIT_FAILURE ); - return NULL; + printf("XCreateWindow failed\n"); + glo_surface_destroy(surface); + return NULL; } XMapWindow(glo.dpy, surface->window); - XCompositeRedirectWindow (glo.dpy, surface->window, CompositeRedirectAutomatic); + XCompositeRedirectWindow(glo.dpy, surface->window, + CompositeRedirectAutomatic); - if(glo.use_ximage) { + if (glo.use_ximage) { surface->pixmap = XCompositeNameWindowPixmap(glo.dpy, surface->window); } else { - surface->pixmap = XCreatePixmap( glo.dpy, DefaultRootWindow(glo.dpy), - width, height, - glo_flags_get_bytes_per_pixel(context->formatFlags)*8); + surface->pixmap = XCreatePixmap(glo.dpy, DefaultRootWindow(glo.dpy), + width, height, + glo_flags_get_bytes_per_pixel(context-> + formatFlags) + * 8); } - if(surface->pixmap == 0) { + if (surface->pixmap == 0) { fprintf(stderr, "Failed to allocate pixmap!\n"); - //exit(EXIT_FAILURE); - return NULL; + glo_surface_destroy(surface); + return NULL; } /* Create a GLX pixmap to associate the frame buffer configuration with the * created X window */ /*XXX: need attribute_list? */ - surface->glxPixmap = glXCreatePixmap( glo.dpy, context->fbConfig, surface->pixmap, NULL ); + surface->glxPixmap = + glXCreatePixmap(glo.dpy, context->fbConfig, surface->pixmap, NULL); if (!surface->glxPixmap) { - printf( "glXCreatePixmap failed\n" ); - //exit( EXIT_FAILURE ); - return NULL; + printf("glXCreatePixmap failed\n"); + glo_surface_destroy(surface); + return NULL; } XSync(glo.dpy, 0); @@ -358,35 +391,43 @@ GloSurface *glo_surface_create(int width, int height, GloContext *context) { sizehints.flags = USSize | USPosition; XSetWMNormalHints(glo.dpy, surface->window, &sizehints); XSetStandardProperties(glo.dpy, surface->window, "", "", None, - (char **) NULL, 0, &sizehints); + (char **)NULL, 0, &sizehints); } XSync(glo.dpy, 0); // If we're using XImages to pull the data from the graphics card... - glo_surface_try_alloc_xshm_image(surface); + if (glo_surface_try_alloc_xshm_image(surface) < 0) { + printf("Failed to allocate shm image\n"); + glo_surface_destroy(surface); + return NULL; + } return surface; } /* Destroy the given surface */ -void glo_surface_destroy(GloSurface *surface) { +void glo_surface_destroy(GloSurface * surface) +{ - if(surface->pixmap) - XFreePixmap( glo.dpy, surface->pixmap); + if (surface->pixmap) + XFreePixmap(glo.dpy, surface->pixmap); - if(surface->glxPixmap) - glXDestroyPixmap( glo.dpy, surface->glxPixmap); + if (surface->glxPixmap) + glXDestroyPixmap(glo.dpy, surface->glxPixmap); - XDestroyWindow( glo.dpy, surface->window); - if(surface->image) + if (surface->window) + XDestroyWindow(glo.dpy, surface->window); + + if (surface->image) glo_surface_free_xshm_image(surface); - g_free(surface); + g_free(surface); } /* Make the given surface current */ -int glo_surface_makecurrent(GloSurface *surface) { +int glo_surface_makecurrent(GloSurface * surface) +{ int ret; if (!glo_inited) @@ -401,79 +442,82 @@ int glo_surface_makecurrent(GloSurface *surface) { return ret; } -void glo_surface_updatecontents(GloSurface *surface) { +void glo_surface_updatecontents(GloSurface * surface) +{ if (!surface) return; - if(glo.use_ximage) { + if (glo.use_ximage) { glXWaitGL(); - if(surface->image) { - XShmGetImage (glo.dpy, surface->pixmap, surface->image, 0, 0, AllPlanes); - } - else { - XGetImage(glo.dpy, surface->pixmap, 0, 0, surface->width, surface->height, AllPlanes, ZPixmap); + if (surface->image) { + XShmGetImage(glo.dpy, surface->pixmap, surface->image, 0, 0, + AllPlanes); + } else { + XGetImage(glo.dpy, surface->pixmap, 0, 0, surface->width, + surface->height, AllPlanes, ZPixmap); } } } /* Get the contents of the given surface */ -void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, void *data) { +void glo_surface_getcontents(GloSurface * surface, int stride, int bpp, + void *data) +{ static int once; XImage *img; if (!surface) return; - if(glo.use_ximage) { + if (glo.use_ximage) { glXWaitGL(); - - if(surface->image) { - XShmGetImage (glo.dpy, surface->pixmap, surface->image, 0, 0, AllPlanes); + + if (surface->image) { + XShmGetImage(glo.dpy, surface->pixmap, surface->image, 0, 0, + AllPlanes); img = surface->image; - } - else { - img = XGetImage(glo.dpy, surface->pixmap, 0, 0, surface->width, surface->height, AllPlanes, ZPixmap); + } else { + img = + XGetImage(glo.dpy, surface->pixmap, 0, 0, surface->width, + surface->height, AllPlanes, ZPixmap); } if (img) { - if(bpp != 32 && bpp != 24 && !once) { + if (bpp != 32 && bpp != 24 && !once) { fprintf(stderr, "Warning: unsupported colourdepth\n"); once = 1; } - if(bpp == img->bits_per_pixel && stride == img->bytes_per_line) - { - memcpy(data, img->data, stride * surface->height); - } - else - { + if (bpp == img->bits_per_pixel && stride == img->bytes_per_line) { + memcpy(data, img->data, stride * surface->height); + } else { int x, y; - for(y = 0 ; y < surface->height ; y++) { - for(x = 0 ; x < surface->width ; x++) { - char *src = ((char*)img->data) + - (x*(img->bits_per_pixel/8)) + - (y*img->bytes_per_line); - char *dst = ((char*)data) + x*(bpp/8) + (y*stride); + for (y = 0; y < surface->height; y++) { + for (x = 0; x < surface->width; x++) { + char *src = ((char *)img->data) + + (x * (img->bits_per_pixel / 8)) + + (y * img->bytes_per_line); + char *dst = + ((char *)data) + x * (bpp / 8) + (y * stride); dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; - if(bpp == 32) - dst[3] = 0xff; // if guest is 32 bit and host is 24 + if (bpp == 32) + dst[3] = 0xff; // if guest is 32 bit and host is 24 } } } - + // If we're not using Shm - if(!surface->image) + if (!surface->image) XDestroyImage(img); - return; // We're done. - } - // Uh oh... better fallback. Perhaps get glo.use_ximage to 0? + return; // We're done. + } + // Uh oh... better fallback. Perhaps get glo.use_ximage to 0? } - // Compatible / fallback method. glo_surface_getcontents_readpixels(surface->context->formatFlags, stride, bpp, surface->width, @@ -481,7 +525,8 @@ void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, void *dat } /* Return the width and height of the given surface */ -void glo_surface_get_size(GloSurface *surface, int *width, int *height) { +void glo_surface_get_size(GloSurface * surface, int *width, int *height) +{ if (width) *width = surface->width; if (height) @@ -489,158 +534,171 @@ void glo_surface_get_size(GloSurface *surface, int *width, int *height) { } /* Bind the surface as texture */ -void glo_surface_as_texture(GloContext *ctxt, GloSurface *surface, int surface_type) +void glo_surface_as_texture(GloContext * ctxt, GloSurface * surface, + int surface_type) { #if 0 - void (*ptr_func_glXBindTexImageEXT) (Display *dpy, GLXDrawable draw, int buffer, int *attrib_list); + void (*ptr_func_glXBindTexImageEXT) (Display * dpy, GLXDrawable draw, + int buffer, int *attrib_list); ptr_func_glXBindTexImageEXT = - (void(*)(Display*, GLXDrawable, int, int*))glo_getprocaddress((const char*)"glXBindTexImageEXT"); + (void (*)(Display *, GLXDrawable, int, int *)) + glo_getprocaddress((const char *)"glXBindTexImageEXT"); - /*XXX: When to call the glXReleaseTexImageEXT?*/ - if (!ptr_func_glXBindTexImageEXT) - { - fprintf (stderr, "glXBindTexImageEXT not supported! Can't emulate glEGLImageTargetTexture2DOES!\n"); + /*XXX: When to call the glXReleaseTexImageEXT? */ + if (!ptr_func_glXBindTexImageEXT) { + fprintf(stderr, + "glXBindTexImageEXT not supported! Can't emulate glEGLImageTargetTexture2DOES!\n"); } fprintf(stderr, "surface_as_texture:error=%d.\n", glGetError()); - ptr_func_glXBindTexImageEXT(glo.dpy, surface->glxPixmap, GLX_FRONT_LEFT_EXT, NULL); + ptr_func_glXBindTexImageEXT(glo.dpy, surface->glxPixmap, GLX_FRONT_LEFT_EXT, + NULL); fprintf(stderr, "surface_as_texture:2:error=%d.\n", glGetError()); #else - int glFormat, glType; + int glFormat, glType; glo_surface_updatecontents(surface); - /*XXX: changet the fixed target: GL_TEXTURE_2D*/ - glo_flags_get_readpixel_type(surface->context->formatFlags, &glFormat, &glType); + /*XXX: changet the fixed target: GL_TEXTURE_2D */ + glo_flags_get_readpixel_type(surface->context->formatFlags, &glFormat, + &glType); /* fprintf(stderr, "surface_as_texture:teximage:width=%d,height=%d, glFormat=0x%x, glType=0x%x.\n", surface->width, surface->height, glFormat, glType);*/ /* glTexImage2D use different RGB order than the contexts in the pixmap surface */ /* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->image->data);*/ - if(surface_type == SURFACE_PBUFFER) - { - if ((glFormat == GL_RGBA || glFormat == GL_BGRA) && glType == GL_UNSIGNED_BYTE) { - GLubyte *b = (GLubyte *)surface->image->data; - int stride = surface->width * 4; - GLubyte *c = &((GLubyte *)surface->image->data)[stride*(surface->height-1)]; - GLubyte *tmp = (GLubyte*)g_malloc(stride); - int irow; - - for(irow = 0; irow < surface->height / 2; irow++) { - memcpy(tmp, b, stride); - memcpy(b, c, stride); - memcpy(c, tmp, stride); - b += stride; - c -= stride; + if (surface_type == SURFACE_PBUFFER) { + if ((glFormat == GL_RGBA || glFormat == GL_BGRA) + && glType == GL_UNSIGNED_BYTE) { + GLubyte *b = (GLubyte *) surface->image->data; + int stride = surface->width * 4; + GLubyte *c = + &((GLubyte *) surface->image->data)[stride * + (surface->height - 1)]; + GLubyte *tmp = (GLubyte *) g_malloc(stride); + int irow; + + for (irow = 0; irow < surface->height / 2; irow++) { + memcpy(tmp, b, stride); + memcpy(b, c, stride); + memcpy(c, tmp, stride); + b += stride; + c -= stride; + } + g_free(tmp); } - g_free(tmp); } - } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, glFormat, glType, surface->image->data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->width, surface->height, 0, + glFormat, glType, surface->image->data); #endif } -void glo_surface_release_texture(GloSurface *surface) +void glo_surface_release_texture(GloSurface * surface) { } /* Abstract glXQueryExtensionString() */ -const char *glo_glXQueryExtensionsString(void) { +const char *glo_glXQueryExtensionsString(void) +{ return glXQueryExtensionsString(glo.dpy, 0); } - #define TX (17) #define TY (16) -static int glo_can_readback(void) { +static int glo_can_readback(void) +{ GloContext *context; GloSurface *surface; - unsigned char *datain = (unsigned char *)g_malloc(4*TX*TY); - unsigned char *datain_flip = (unsigned char *)g_malloc(4*TX*TY); // flipped input data (for GL) + unsigned char *datain = (unsigned char *)g_malloc(4 * TX * TY); + unsigned char *datain_flip = (unsigned char *)g_malloc(4 * TX * TY); // flipped input data (for GL) unsigned char *dataout; unsigned char *p; - int x,y; + int x, y; const int bufferAttributes[] = { - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 0, - GLX_STENCIL_SIZE, 0, - 0, - }; + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 0, + GLX_STENCIL_SIZE, 0, + 0, + }; int bufferFlags = glo_flags_get_from_glx(bufferAttributes, 0); int bpp = glo_flags_get_bytes_per_pixel(bufferFlags); int glFormat, glType; - memset(datain_flip, 0, TX*TY*4); - memset(datain, 0, TX*TY*4); + memset(datain_flip, 0, TX * TY * 4); + memset(datain, 0, TX * TY * 4); p = datain; - for (y=0;y2) p[2] = 0; - if (bpp>3) p[3] = 0xFF; - p+=bpp; + if (bpp > 2) + p[2] = 0; + if (bpp > 3) + p[3] = 0xFF; + p += bpp; } - memcpy(&datain_flip[((TY-1)-y)*bpp*TX], &datain[y*bpp*TX], bpp*TX); + memcpy(&datain_flip[((TY - 1) - y) * bpp * TX], &datain[y * bpp * TX], + bpp * TX); } context = glo_context_create(bufferFlags, 0); - if (context == NULL) { - g_free(datain); - g_free(datain_flip); - return 1; - } + if (context == NULL) { + g_free(datain); + g_free(datain_flip); + return 1; + } surface = glo_surface_create(TX, TY, context); - if (surface == NULL) { - g_free(datain); - g_free(datain_flip); - return 1; - } + if (surface == NULL) { + g_free(datain); + g_free(datain_flip); + return 1; + } glo_surface_makecurrent(surface); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0,TX, 0,TY, 0, 1); + glOrtho(0, TX, 0, TY, 0, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glRasterPos2f(0,0); + glRasterPos2f(0, 0); glo_flags_get_readpixel_type(bufferFlags, &glFormat, &glType); - glDrawPixels(TX,TY,glFormat, glType, datain_flip); + glDrawPixels(TX, TY, glFormat, glType, datain_flip); glFlush(); - dataout = (unsigned char *)g_malloc(4*TX*TY); - memset(dataout, 0, bpp*TX*TY); + dataout = (unsigned char *)g_malloc(4 * TX * TY); + memset(dataout, 0, bpp * TX * TY); - glo_surface_getcontents(surface, TX*4, bpp*8, dataout); + glo_surface_getcontents(surface, TX * 4, bpp * 8, dataout); glo_surface_destroy(surface); glo_context_destroy(context); - if (memcmp(datain, dataout, bpp*TX*TY)==0) { - g_free(datain); - g_free(datain_flip); - g_free(dataout); + if (memcmp(datain, dataout, bpp * TX * TY) == 0) { + g_free(datain); + g_free(datain_flip); + g_free(dataout); return 1; - } + } - g_free(datain); - g_free(datain_flip); - g_free(dataout); + g_free(datain); + g_free(datain_flip); + g_free(dataout); return 0; } -static void glo_test_readback_methods(void) { +static void glo_test_readback_methods(void) +{ glo.use_ximage = 1; - if(!glo_can_readback()) + if (!glo_can_readback()) glo.use_ximage = 0; //fprintf(stderr, "VM GL: Using %s readback\n", glo.use_ximage?"XImage":"glReadPixels"); diff --git a/tizen/src/hw/helper_opengl.c b/tizen/src/hw/helper_opengl.c index c09b914a69..ab929d0884 100644 --- a/tizen/src/hw/helper_opengl.c +++ b/tizen/src/hw/helper_opengl.c @@ -34,6 +34,7 @@ #include "opengl_func.h" #include "opengl_process.h" #include "opengl_exec.h" +#include "helper_opengl.h" #include "tizen/src/debug_ch.h" MULTI_DEBUG_CHANNEL(qemu, opengl); @@ -43,7 +44,7 @@ MULTI_DEBUG_CHANNEL(qemu, opengl); #ifdef _WIN32 #define DEBUGF(...) printf(__VA_ARGS__) #else -extern struct FILE *stderr; /* Standard error output stream. */ +extern struct FILE *stderr; /* Standard error output stream. */ #define DEBUGF(...) fprintf(stderr, __VA_ARGS__) #endif #endif @@ -58,72 +59,71 @@ extern struct FILE *stderr; /* Standard error output stream. */ typedef unsigned long host_ptr; -static inline int do_decode_call_int(ProcessStruct *process, void *args_in, int args_len, char *r_buffer) +static inline int do_decode_call_int(ProcessStruct * process, void *args_in, + int args_len, char *r_buffer) { Signature *signature; int i, ret; - char *argptr, *tmp; - static void* args[50]; + char *argptr; + static host_ptr args[50]; int func_number; #ifdef __APPLE__ char temp4mac[256]; #endif - if(!args_len) - return 0; + if (!args_len) + return 0; argptr = args_in; - while((char*)argptr < (char*)args_in + args_len) { - func_number = *(short*)argptr; + while ((char *)argptr < (char *)args_in + args_len) { + func_number = *(short *)argptr; argptr += 2; - if(func_number >= GL_N_CALLS) { + if (func_number >= GL_N_CALLS) { DEBUGF("Bad function number or corrupt command queue\n"); return 0; } signature = (Signature *) tab_opengl_calls[func_number]; - tmp = argptr; - for (i = 0; i < signature->nb_args; i++) { - int args_size = *(int*)argptr; - argptr+=4; + int args_size = *(int *)argptr; + argptr += 4; switch (signature->args_type[i]) { - case TYPE_UNSIGNED_INT: - case TYPE_INT: - case TYPE_UNSIGNED_CHAR: - case TYPE_CHAR: - case TYPE_UNSIGNED_SHORT: - case TYPE_SHORT: - case TYPE_FLOAT: - args[i] = *(int*)argptr; + case TYPE_UNSIGNED_INT: + case TYPE_INT: + case TYPE_UNSIGNED_CHAR: + case TYPE_CHAR: + case TYPE_UNSIGNED_SHORT: + case TYPE_SHORT: + case TYPE_FLOAT: + args[i] = *(int *)argptr; break; - case TYPE_NULL_TERMINATED_STRING: - CASE_IN_UNKNOWN_SIZE_POINTERS: + case TYPE_NULL_TERMINATED_STRING: + CASE_IN_UNKNOWN_SIZE_POINTERS: { - if(*(int*)argptr) - args[i] = (host_ptr)argptr+4; + if (*(int *)argptr) + args[i] = (host_ptr) argptr + 4; else - args[i] = (host_ptr)NULL; + args[i] = (host_ptr) NULL; if ((args[i] == 0 && args_size == 0 && - !IS_NULL_POINTER_OK_FOR_FUNC(func_number)) || + !IS_NULL_POINTER_OK_FOR_FUNC(func_number)) || (args[i] == 0 && args_size != 0)) - return 0; + return 0; argptr += 4; break; } - CASE_IN_LENGTH_DEPENDING_ON_PREVIOUS_ARGS: + CASE_IN_LENGTH_DEPENDING_ON_PREVIOUS_ARGS: { - if(*(int*)argptr) - args[i] = (host_ptr)argptr+4; + if (*(int *)argptr) + args[i] = (host_ptr) argptr + 4; else - args[i] = (host_ptr)NULL; + args[i] = (host_ptr) NULL; if (args[i] == 0 && args_size != 0) return 0; @@ -132,41 +132,40 @@ static inline int do_decode_call_int(ProcessStruct *process, void *args_in, int break; } - CASE_OUT_POINTERS: + CASE_OUT_POINTERS: { - /* NULL pointer is used as output pointer - since the argument size is zero. */ - if (args_size == 0) { - *(int*)r_buffer = 0; - r_buffer += 4; + /* NULL pointer is used as output pointer + since the argument size is zero. */ + if (args_size == 0) { + *(int *)r_buffer = 0; + r_buffer += 4; #ifdef __APPLE__ /*On MAC OS, GL call glGetProgramInfoLog and glGetShaderInfoLog will crash if ouput pointer is NULL*/ - args[i] = temp4mac; + args[i] = (host_ptr) temp4mac; #else - args[i] = NULL; + args[i] = (host_ptr) NULL; #endif - } else if(*(int*)argptr) { - *(int*)r_buffer = args_size; - r_buffer+=4; - args[i] = (host_ptr)r_buffer; + } else if (*(int *)argptr) { + *(int *)r_buffer = args_size; + r_buffer += 4; + args[i] = (host_ptr) r_buffer; r_buffer += args_size; - } - else { + } else { args[i] = 0; } argptr += 4; args_size = 0; break; - } + } - case TYPE_DOUBLE: - CASE_IN_KNOWN_SIZE_POINTERS: + case TYPE_DOUBLE: + CASE_IN_KNOWN_SIZE_POINTERS: { - if(*(int*)argptr) - args[i] = (host_ptr)argptr+4; + if (*(int *)argptr) + args[i] = (host_ptr) argptr + 4; else - args[i] = (host_ptr)NULL; + args[i] = (host_ptr) NULL; if (args[i] == 0 && args_size != 0) return 0; @@ -175,29 +174,29 @@ static inline int do_decode_call_int(ProcessStruct *process, void *args_in, int break; } - case TYPE_IN_IGNORED_POINTER: - args[i] = 0; - break; + case TYPE_IN_IGNORED_POINTER: + args[i] = 0; + break; - default: - DEBUGF( "Oops : call %s arg %d pid=%d\n", - tab_opengl_calls_name[func_number], i, - process->process_id); - return 0; + default: + DEBUGF("Oops : call %s arg %d pid=%d\n", + tab_opengl_calls_name[func_number], i, + process->process_id); + return 0; } argptr += args_size; } - if((char*)argptr > (char*)args_in + args_len) { + if ((char *)argptr > (char *)args_in + args_len) { DEBUGF("Client bug: malformed command, killing process\n"); return 0; } if (signature->ret_type == TYPE_CONST_CHAR) - r_buffer[0] = 0; // In case high bits are set. + r_buffer[0] = 0; // In case high bits are set. ret = do_function_call(process, func_number, args, r_buffer); - switch(signature->ret_type) { + switch (signature->ret_type) { case TYPE_INT: case TYPE_UNSIGNED_INT: memcpy(r_buffer, &ret, sizeof(int)); @@ -210,10 +209,10 @@ static inline int do_decode_call_int(ProcessStruct *process, void *args_in, int case TYPE_NONE: break; default: - DEBUGF("Unsupported GL API return type %i!\n", signature->ret_type); - exit (-1); + DEBUGF("Unsupported GL API return type %i!\n", signature->ret_type); + exit(-1); } - } // endwhile + } // endwhile /* switch(signature->ret_type) { case TYPE_INT: @@ -234,64 +233,66 @@ static inline int do_decode_call_int(ProcessStruct *process, void *args_in, int */ return 1; } + #define GL_PASSINGTHROUGH_ABI 1 #define GLINIT_FAIL_ABI 3 #define GLINIT_QUEUE 2 #define GLINIT_NOQUEUE 1 -int decode_call_int(ProcessStruct *process, char *in_args, int args_len, char *r_buffer) +int decode_call_int(ProcessStruct * process, char *in_args, int args_len, + char *r_buffer) { - static ProcessStruct *cur_process = NULL; - int ret; - int first_func = *(short*)in_args; - - /* Select the appropriate context for this pid if it isnt already active - * Note: if we're about to execute glXMakeCurrent() then we tell the - * renderer not to waste its time switching contexts - */ - - if (cur_process != process) { - cur_process = process; - vmgl_context_switch(cur_process, (first_func == glXMakeCurrent_func)?0:1); - } - - if(unlikely(first_func == _init32_func || first_func == _init64_func)) { - if(!cur_process->wordsize) { - int *version = (int*)(in_args+2); - cur_process->wordsize = first_func == _init32_func?4:8; - - if((version[0] != 1) || (version[1] < GL_PASSINGTHROUGH_ABI)) { - *(int*)r_buffer = GLINIT_FAIL_ABI; // ABI check FAIL - TRACE("Error! The GL passing through package in the image does not match the version of QEMUGL. Please update the image!\n"); - exit (1); - } else if(version[1] > GL_PASSINGTHROUGH_ABI) { - *(int*)r_buffer = GLINIT_FAIL_ABI; // ABI check FAIL - TRACE("Error! The GL passing through package in the image does not match the version of QEMUGL. Please update the QEMUGL!\n"); - exit (1); - } - else - *(int*)r_buffer = GLINIT_QUEUE; // Indicate that we can buffer commands - - return 1; // Initialisation done - } - else { - DEBUGF("Attempt to init twice. Continuing regardless.\n"); - return 1; - } - } - - if(unlikely(first_func == -1 || !cur_process->wordsize)) { - if(!cur_process->wordsize && first_func != -1) - DEBUGF("commands submitted before process init.\n"); - ret = 0; - } - else { - ret = do_decode_call_int(cur_process, in_args, args_len, r_buffer); - } - - if(!ret) - cur_process = NULL; - - return ret; + static ProcessStruct *cur_process = NULL; + int ret; + int first_func = *(short *)in_args; + + /* Select the appropriate context for this pid if it isnt already active + * Note: if we're about to execute glXMakeCurrent() then we tell the + * renderer not to waste its time switching contexts + */ + + if (cur_process != process) { + cur_process = process; + vmgl_context_switch(cur_process, + (first_func == glXMakeCurrent_func) ? 0 : 1); + } + + if (unlikely(first_func == _init32_func || first_func == _init64_func)) { + if (!cur_process->wordsize) { + int *version = (int *)(in_args + 2); + cur_process->wordsize = first_func == _init32_func ? 4 : 8; + + if ((version[0] != 1) || (version[1] < GL_PASSINGTHROUGH_ABI)) { + *(int *)r_buffer = GLINIT_FAIL_ABI; // ABI check FAIL + TRACE + ("Error! The GL passing through package in the image does not match the version of QEMUGL. Please update the image!\n"); + exit(1); + } else if (version[1] > GL_PASSINGTHROUGH_ABI) { + *(int *)r_buffer = GLINIT_FAIL_ABI; // ABI check FAIL + TRACE + ("Error! The GL passing through package in the image does not match the version of QEMUGL. Please update the QEMUGL!\n"); + exit(1); + } else + *(int *)r_buffer = GLINIT_QUEUE; // Indicate that we can buffer commands + + return 1; // Initialisation done + } else { + DEBUGF("Attempt to init twice. Continuing regardless.\n"); + return 1; + } + } + + if (unlikely(first_func == -1 || !cur_process->wordsize)) { + if (!cur_process->wordsize && first_func != -1) + DEBUGF("commands submitted before process init.\n"); + ret = 0; + } else { + ret = do_decode_call_int(cur_process, in_args, args_len, r_buffer); + } + + if (!ret) + cur_process = NULL; + + return ret; } diff --git a/tizen/src/hw/helper_opengl.h b/tizen/src/hw/helper_opengl.h new file mode 100644 index 0000000000..b422345527 --- /dev/null +++ b/tizen/src/hw/helper_opengl.h @@ -0,0 +1,28 @@ +/* + * Host-side implementation of GL/GLX API + * + * Copyright (c) 2013 Intel Corporation + * + * 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, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#include "opengl_process.h" + +int decode_call_int(ProcessStruct * p, char *in_args, int args_len, + char *r_buffer); diff --git a/tizen/src/hw/maru_board.c b/tizen/src/hw/maru_board.c index 23262bc84f..a8f2596754 100644 --- a/tizen/src/hw/maru_board.c +++ b/tizen/src/hw/maru_board.c @@ -12,7 +12,7 @@ * SungMin Ha * MunKyu Im * JiHye Kim - * GiWoong Kim + * GiWoong Kim * DongKyun Yun * DoHyung Hong * Hyunjun Son @@ -68,7 +68,7 @@ #include "maru_pm.h" int codec_init(PCIBus *bus); - +int maru_brill_codec_pci_device_init(PCIBus *bus); #define MAX_IDE_BUS 2 @@ -333,7 +333,8 @@ static void maru_x86_machine_init(MemoryRegion *system_memory, // maru specialized device init... if (pci_enabled) { - codec_init(pci_bus); +// codec_init(pci_bus); + maru_brill_codec_pci_device_init(pci_bus); } #ifdef CONFIG_YAGL pci_create_simple(pci_bus, -1, "yagl"); diff --git a/tizen/src/hw/maru_brill_codec.c b/tizen/src/hw/maru_brill_codec.c new file mode 100644 index 0000000000..d2fe49bf81 --- /dev/null +++ b/tizen/src/hw/maru_brill_codec.c @@ -0,0 +1,1837 @@ +/* + * Virtual Codec Device + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Kitae Kim + * SeokYeon Hwang + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "maru_brill_codec.h" + +/* define debug channel */ +MULTI_DEBUG_CHANNEL(qemu, brillcodec); + +// device +#define CODEC_DEVICE_NAME "brilcodec" +#define CODEC_VERSION 1 + +// device memory +#define CODEC_META_DATA_SIZE (256) + +#define CODEC_MEM_SIZE (32 * 1024 * 1024) +#define CODEC_REG_SIZE (256) + +// libav +#define GEN_MASK(x) ((1 << (x)) - 1) +#define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x)) +#define ROUND_UP_2(x) ROUND_UP_X(x, 1) +#define ROUND_UP_4(x) ROUND_UP_X(x, 2) +#define ROUND_UP_8(x) ROUND_UP_X(x, 3) +#define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x)) + +#define DEFAULT_VIDEO_GOP_SIZE 15 + + +// define a queue to manage ioparam, context data +typedef struct DeviceMemEntry { + uint8_t *buf; + uint32_t buf_size; + uint32_t buf_id; + uint32_t ctx_id; + + QTAILQ_ENTRY(DeviceMemEntry) node; +} DeviceMemEntry; + +typedef struct CodecDataStg { + CodecParam *param_buf; + DeviceMemEntry *data_buf; + + QTAILQ_ENTRY(CodecDataStg) node; +} CodecDataStg; + +// define two queue to store input and output buffers. +static QTAILQ_HEAD(codec_wq, DeviceMemEntry) codec_wq = + QTAILQ_HEAD_INITIALIZER(codec_wq); + +static QTAILQ_HEAD(codec_rq, CodecDataStg) codec_rq = + QTAILQ_HEAD_INITIALIZER(codec_rq); + +static DeviceMemEntry *entry[CODEC_CONTEXT_MAX]; + +// pixel info +typedef struct PixFmtInfo { + uint8_t x_chroma_shift; + uint8_t y_chroma_shift; +} PixFmtInfo; + +static PixFmtInfo pix_fmt_info[PIX_FMT_NB]; + +// thread +static int worker_thread_cnt = 0; +static int idle_thread_cnt = 0; +#define DEFAULT_WORKER_THREAD_CNT 8 + +static void *maru_brill_codec_threads(void *opaque); + +// irq +static int irq_raised = 0; + +// static void maru_brill_codec_reset_parser_info(MaruBrillCodecState *s, int32_t ctx_index); +static int maru_brill_codec_query_list(MaruBrillCodecState *s); +static void maru_brill_codec_release_context(MaruBrillCodecState *s, int32_t value); + +// codec functions +static bool codec_init(MaruBrillCodecState *, int, int, void *); +static bool codec_deinit(MaruBrillCodecState *, int, int, void *); +static bool codec_decode_video(MaruBrillCodecState *, int, int, void *); +static bool codec_encode_video(MaruBrillCodecState *, int, int, void *); +static bool codec_decode_audio(MaruBrillCodecState *, int, int, void *); +static bool codec_encode_audio(MaruBrillCodecState *, int , int, void *); +static bool codec_picture_copy(MaruBrillCodecState *, int , int, void *); +static bool codec_flush_buffers(MaruBrillCodecState *, int , int, void *); + +typedef bool (*CodecFuncEntry)(MaruBrillCodecState *, int, int, void *); +static CodecFuncEntry codec_func_handler[] = { + codec_init, + codec_decode_video, + codec_encode_video, + codec_decode_audio, + codec_encode_audio, + codec_picture_copy, + codec_deinit, + codec_flush_buffers, +}; + +static AVCodecParserContext *maru_brill_codec_parser_init(AVCodecContext *avctx); +#if 0 +static int maru_brill_codec_parser_parse (AVCodecParserContext *pctx, AVCodecContext *avctx, + uint8_t *inbuf, int inbuf_size, + int64_t pts, int64_t dts, int64_t pos); +#endif + +static void maru_brill_codec_pop_writequeue(MaruBrillCodecState *s, int32_t f_id); +static void maru_brill_codec_push_readqueue(MaruBrillCodecState *s, CodecParam *ioparam); +static void maru_brill_codec_push_writequeue(MaruBrillCodecState *s, void* buf, + uint32_t buf_size, int ctx_id, int f_id); + +static void *maru_brill_codec_store_inbuf(uint8_t *mem_base_offset, CodecParam *ioparam); + +static void maru_brill_codec_get_cpu_cores(void) +{ + worker_thread_cnt = get_number_of_processors(); + if (worker_thread_cnt < DEFAULT_WORKER_THREAD_CNT) { + worker_thread_cnt = DEFAULT_WORKER_THREAD_CNT; + } + + TRACE("number of threads: %d\n", worker_thread_cnt); +} + +static void maru_brill_codec_threads_create(MaruBrillCodecState *s) +{ + int index; + QemuThread *pthread = NULL; + + TRACE("enter: %s\n", __func__); + + pthread = g_malloc(sizeof(QemuThread) * worker_thread_cnt); + if (!pthread) { + ERR("failed to allocate threadpool memory.\n"); + return; + } + + qemu_cond_init(&s->threadpool.cond); + qemu_mutex_init(&s->threadpool.mutex); + + s->is_thread_running = 1; + + for (index = 0; index < worker_thread_cnt; index++) { + qemu_thread_create(&pthread[index], + maru_brill_codec_threads, (void *)s, QEMU_THREAD_JOINABLE); + } + + s->threadpool.threads = pthread; + + TRACE("leave: %s\n", __func__); +} + +static void maru_brill_codec_thread_exit(MaruBrillCodecState *s) +{ + int index; + + TRACE("enter: %s\n", __func__); + + /* stop to run dedicated threads. */ + s->is_thread_running = 0; + + for (index = 0; index < worker_thread_cnt; index++) { + qemu_thread_join(&s->threadpool.threads[index]); + } + + TRACE("destroy mutex and conditional.\n"); + qemu_mutex_destroy(&s->threadpool.mutex); + qemu_cond_destroy(&s->threadpool.cond); + + if (s->threadpool.threads) { + g_free(s->threadpool.threads); + s->threadpool.threads = NULL; + } + + TRACE("leave: %s\n", __func__); +} + +static void maru_brill_codec_wakeup_threads(MaruBrillCodecState *s, int api_index) +{ + CodecParam *ioparam = NULL; + + ioparam = g_malloc0(sizeof(CodecParam)); + memcpy(ioparam, &s->ioparam, sizeof(CodecParam)); + + TRACE("wakeup thread. ctx_id: %u, api_id: %u, mem_offset: 0x%x\n", + ioparam->ctx_index, ioparam->api_index, ioparam->mem_offset); + + maru_brill_codec_push_readqueue(s, ioparam); + + qemu_mutex_lock(&s->context_mutex); + // W/A for threads starvation. + while (idle_thread_cnt == 0) { + qemu_mutex_unlock(&s->context_mutex); + TRACE("Worker threads are exhausted\n"); + usleep(2000); // wait 2ms. + qemu_mutex_lock(&s->context_mutex); + } + qemu_cond_signal(&s->threadpool.cond); + qemu_mutex_unlock(&s->context_mutex); + + TRACE("after sending conditional signal\n"); +} + +static void *maru_brill_codec_threads(void *opaque) +{ + MaruBrillCodecState *s = (MaruBrillCodecState *)opaque; + + TRACE("enter: %s\n", __func__); + + while (s->is_thread_running) { + int ctx_id, f_id, api_id; + CodecDataStg *elem = NULL; + DeviceMemEntry *indata_buf = NULL; + + qemu_mutex_lock(&s->context_mutex); + ++idle_thread_cnt; // protected under mutex. + qemu_cond_wait(&s->threadpool.cond, &s->context_mutex); + --idle_thread_cnt; // protected under mutex. + qemu_mutex_unlock(&s->context_mutex); + + qemu_mutex_lock(&s->ioparam_queue_mutex); + elem = QTAILQ_FIRST(&codec_rq); + if (elem) { + QTAILQ_REMOVE(&codec_rq, elem, node); + qemu_mutex_unlock(&s->ioparam_queue_mutex); + } else { + qemu_mutex_unlock(&s->ioparam_queue_mutex); + continue; + } + + api_id = elem->param_buf->api_index; + ctx_id = elem->param_buf->ctx_index; + f_id = elem->param_buf->file_index; + indata_buf = elem->data_buf; + + TRACE("api_id: %d ctx_id: %d f_id: %x\n", api_id, ctx_id, f_id); + + if (!codec_func_handler[api_id](s, ctx_id, f_id, indata_buf)) { + ERR("codec_func failure.\n"); + continue; + } + + if (elem) { + TRACE("release an element of CodecDataStg\n"); + + if (elem->param_buf) { + TRACE("release a buffer of CodecParam\n"); + g_free(elem->param_buf); + } + + if (elem->data_buf) { + + if (elem->data_buf->buf) { + TRACE("release inbuf\n"); + g_free(elem->data_buf->buf); + } + + TRACE("release a buffer indata_buf\n"); + g_free(elem->data_buf); + } + + g_free(elem); + } + + if (api_id == CODEC_DEINIT) { + TRACE("deinit doesn't need to raise interrupt.\n"); + } else { + TRACE("switch context to raise interrupt.\n"); + qemu_bh_schedule(s->codec_bh); + } + } + + maru_brill_codec_thread_exit(s); + + TRACE("leave: %s\n", __func__); + return NULL; +} + +// queue +static void maru_brill_codec_push_readqueue(MaruBrillCodecState *s, + CodecParam *ioparam) +{ + CodecDataStg *elem = NULL; + DeviceMemEntry *data_buf = NULL; + + elem = g_malloc0(sizeof(CodecDataStg)); + if (!elem) { + ERR("failed to allocate ioparam_queue. %d\n", sizeof(CodecDataStg)); + return; + } + + elem->param_buf = ioparam; + + switch(ioparam->api_index) { + case CODEC_DECODE_VIDEO ... CODEC_ENCODE_AUDIO: + data_buf = maru_brill_codec_store_inbuf((uint8_t *)s->vaddr, ioparam); + break; + default: + TRACE("no buffer from guest\n"); + break; + } + + elem->data_buf = data_buf; + + qemu_mutex_lock(&s->ioparam_queue_mutex); + QTAILQ_INSERT_TAIL(&codec_rq, elem, node); + qemu_mutex_unlock(&s->ioparam_queue_mutex); +} + +static void *maru_brill_codec_store_inbuf(uint8_t *mem_base_offset, + CodecParam *ioparam) +{ + DeviceMemEntry *elem = NULL; + int readbuf_size, size = 0; + uint8_t *readbuf = NULL; + uint8_t *device_mem = NULL; + + device_mem = mem_base_offset + ioparam->mem_offset; + if (!device_mem) { + ERR("[%d] device memory region is null\n"); + return NULL; + } + + elem = g_malloc0(sizeof(DeviceMemEntry)); + if (!elem) { + ERR("failed to allocate readqueue node. size: %d\n", + sizeof(DeviceMemEntry)); + return NULL; + } + + memcpy(&readbuf_size, device_mem, sizeof(readbuf_size)); + size = sizeof(readbuf_size); + + TRACE("readbuf size: %d\n", readbuf_size); + if (readbuf_size <= 0) { + TRACE("inbuf size is zero. api_id: %d, ctx_id: %d, mem_offset: %x\n", + readbuf_size, ioparam->api_index, ioparam->ctx_index, ioparam->mem_offset); + } else { + readbuf = g_malloc0(readbuf_size); + if (!readbuf) { + ERR("failed to allocate a read buffer. size: %d\n", readbuf_size); + } else { + TRACE("copy input buffer from guest. ctx_id: %d, mem_offset: %x\n", + ioparam->ctx_index, ioparam->mem_offset); + memcpy(readbuf, device_mem + size, readbuf_size); + } + } + memset(device_mem, 0x00, sizeof(readbuf_size)); + + elem->buf = readbuf; + elem->buf_size = readbuf_size; + elem->buf_id = ioparam->file_index; + elem->ctx_id = ioparam->ctx_index; + + return elem; +} + +static void maru_brill_codec_push_writequeue(MaruBrillCodecState *s, void* buf, + uint32_t buf_size, int ctx_id, int f_id) +{ + DeviceMemEntry *elem = NULL; + elem = g_malloc0(sizeof(DeviceMemEntry)); + + elem->buf = buf; + elem->buf_size = buf_size; + elem->buf_id = f_id; + elem->ctx_id = ctx_id; + + qemu_mutex_lock(&s->context_queue_mutex); + QTAILQ_INSERT_TAIL(&codec_wq, elem, node); + qemu_mutex_unlock(&s->context_queue_mutex); +} + +static void maru_brill_codec_pop_writequeue(MaruBrillCodecState *s, int32_t file_index) +{ + DeviceMemEntry *elem = NULL; + uint32_t mem_offset = 0, ctx_idx; + + TRACE("enter: %s\n", __func__); + + for (ctx_idx = 1; ctx_idx < CODEC_CONTEXT_MAX; ctx_idx++) { + if (s->context[ctx_idx].file_index == file_index) { + break; + } + } + + if (ctx_idx == CODEC_CONTEXT_MAX) { + ERR("failed to find a proper entry via file_index. %x\n", file_index); + return; + } + + TRACE("pop_writeqeue. context index: %d\n", ctx_idx); + + elem = entry[ctx_idx]; + if (elem) { + mem_offset = s->ioparam.mem_offset; + + // check corrupted mem_offset + if (mem_offset < CODEC_MEM_SIZE) { + if (elem->buf) { + TRACE("write data %d to guest. mem_offset: 0x%x\n", + elem->buf_size, mem_offset); + memcpy(s->vaddr + mem_offset, elem->buf, elem->buf_size); + + TRACE("release output buffer: %p\n", elem->buf); + g_free(elem->buf); + } + } else { + TRACE("mem_offset is corrupted!!\n"); + } + + TRACE("pop_writequeue. release elem: %p\n", elem); + g_free(elem); + + entry[ctx_idx] = NULL; + } else { + TRACE("there is no buffer to copy data to guest\n"); + } + + TRACE("leave: %s\n", __func__); +} + +static void serialize_video_data(const struct video_data *video, + AVCodecContext *avctx) +{ + if (video->width) { + avctx->width = video->width; + } + if (video->height) { + avctx->height = video->height; + } + if (video->fps_n) { + avctx->time_base.num = video->fps_n; + } + if (video->fps_d) { + avctx->time_base.den = video->fps_d; + } + if (video->pix_fmt > PIX_FMT_NONE) { + avctx->pix_fmt = video->pix_fmt; + } + if (video->par_n) { + avctx->sample_aspect_ratio.num = video->par_n; + } + if (video->par_d) { + avctx->sample_aspect_ratio.den = video->par_d; + } + if (video->bpp) { + avctx->bits_per_coded_sample = video->bpp; + } + if (video->ticks_per_frame) { + avctx->ticks_per_frame = video->ticks_per_frame; + } +} + +static void deserialize_video_data (const AVCodecContext *avctx, + struct video_data *video) +{ + memset(video, 0x00, sizeof(struct video_data)); + + video->width = avctx->width; + video->height = avctx->height; + video->fps_n = avctx->time_base.num; + video->fps_d = avctx->time_base.den; + video->pix_fmt = avctx->pix_fmt; + video->par_n = avctx->sample_aspect_ratio.num; + video->par_d = avctx->sample_aspect_ratio.den; + video->bpp = avctx->bits_per_coded_sample; + video->ticks_per_frame = avctx->ticks_per_frame; +} + +static void serialize_audio_data (const struct audio_data *audio, + AVCodecContext *avctx) +{ + if (audio->channels) { + avctx->channels = audio->channels; + } + if (audio->sample_rate) { + avctx->sample_rate = audio->sample_rate; + } + if (audio->block_align) { + avctx->block_align = audio->block_align; + } + + if (audio->sample_fmt > AV_SAMPLE_FMT_NONE) { + avctx->sample_fmt = audio->sample_fmt; + } +} + +#if 0 +static void maru_brill_codec_reset_parser_info(MaruBrillCodecState *s, int32_t ctx_index) +{ + s->context[ctx_index].parser_buf = NULL; + s->context[ctx_index].parser_use = false; +} +#endif + +static void maru_brill_codec_release_context(MaruBrillCodecState *s, int32_t file_index) +{ + DeviceMemEntry *wq_elem = NULL, *wnext = NULL; + CodecDataStg *rq_elem = NULL, *rnext = NULL; + int ctx_id; + + TRACE("enter: %s\n", __func__); + + qemu_mutex_lock(&s->threadpool.mutex); + for (ctx_id = 1; ctx_id < CODEC_CONTEXT_MAX; ctx_id++) { + if (s->context[ctx_id].file_index == file_index) { + TRACE("reset %d context\n", ctx_id); + s->context[ctx_id].occupied = false; + break; + } + } + qemu_mutex_unlock(&s->threadpool.mutex); + + if (ctx_id == CODEC_CONTEXT_MAX) { + WARN("cannot find a context for 0x%x\n", file_index); + } else { + codec_deinit(s, ctx_id, file_index, NULL); + + QTAILQ_FOREACH_SAFE(rq_elem, &codec_rq, node, rnext) { + if (rq_elem && rq_elem->data_buf && + (rq_elem->data_buf->buf_id == file_index)) { + TRACE("remove unused node from codec_rq. file: %p\n", file_index); + qemu_mutex_lock(&s->context_queue_mutex); + QTAILQ_REMOVE(&codec_rq, rq_elem, node); + qemu_mutex_unlock(&s->context_queue_mutex); + if (rq_elem && rq_elem->data_buf) { + TRACE("release_context. release rq_buffer: %p\n", + rq_elem->data_buf); + g_free(rq_elem->data_buf); + } + + TRACE("release rq_elem: %p\n", rq_elem); + g_free(rq_elem); + } else { + TRACE("remain this node in the codec_rq. %x\n", + rq_elem->data_buf->buf_id); + } + } + + QTAILQ_FOREACH_SAFE(wq_elem, &codec_wq, node, wnext) { + if (wq_elem && wq_elem->buf_id == file_index) { + TRACE("remove nodes from codec_wq." + " elem: %p, buf_id: %p, ctx_id: %d\n", wq_elem, wq_elem->ctx_id, file_index); + qemu_mutex_lock(&s->context_queue_mutex); + QTAILQ_REMOVE(&codec_wq, wq_elem, node); + qemu_mutex_unlock(&s->context_queue_mutex); + + if (wq_elem && wq_elem->buf) { + TRACE("release_context. release wq_buffer: %p\n", wq_elem->buf); + g_free(wq_elem->buf); + wq_elem->buf = NULL; + } + + TRACE("release wq_elem: %p\n", wq_elem); + g_free(wq_elem); + } else { + TRACE("remain this node in the codec_wq. :%x\n", wq_elem->buf_id); + } + } +// maru_brill_codec_reset_parser_info(s, ctx_id); + } + + TRACE("leave: %s\n", __func__); +} + + +// initialize each pixel format. +static void maru_brill_codec_pixfmt_info_init(void) +{ + /* YUV formats */ + pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1; + pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1; + + pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1; + pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0; + pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1; + pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2; + pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2; + + pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2; + pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_YUVJ420P].x_chroma_shift = 1; + pix_fmt_info[PIX_FMT_YUVJ420P].y_chroma_shift = 1; + + pix_fmt_info[PIX_FMT_YUVJ422P].x_chroma_shift = 1; + pix_fmt_info[PIX_FMT_YUVJ422P].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_YUVJ444P].x_chroma_shift = 0; + pix_fmt_info[PIX_FMT_YUVJ444P].y_chroma_shift = 0; + + /* RGB formats */ + pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0; + pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0; + pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0; + pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0; + pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0; + pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_YUVA420P].x_chroma_shift = 1; + pix_fmt_info[PIX_FMT_YUVA420P].y_chroma_shift = 1; +} + +static int maru_brill_codec_get_picture_size(AVPicture *picture, uint8_t *ptr, + int pix_fmt, int width, + int height, bool encode) +{ + int size, w2, h2, size2; + int stride, stride2; + int fsize; + PixFmtInfo *pinfo; + + pinfo = &pix_fmt_info[pix_fmt]; + + switch (pix_fmt) { + case PIX_FMT_YUV420P: + case PIX_FMT_YUV422P: + case PIX_FMT_YUV444P: + case PIX_FMT_YUV410P: + case PIX_FMT_YUV411P: + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUVJ444P: + stride = ROUND_UP_4(width); + h2 = ROUND_UP_X(height, pinfo->y_chroma_shift); + size = stride * h2; + w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift); + stride2 = ROUND_UP_4(w2); + h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift); + size2 = stride2 * h2; + fsize = size + 2 * size2; + TRACE("stride: %d, stride2: %d, size: %d, size2: %d, fsize: %d\n", + stride, stride2, size, size2, fsize); + + if (!encode && !ptr) { + TRACE("allocate a buffer for a decoded picture.\n"); + ptr = av_mallocz(fsize); + if (!ptr) { + ERR("[%d] failed to allocate memory.\n", __LINE__); + return -1; + } + } + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->data[3] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = stride2; + picture->linesize[2] = stride2; + picture->linesize[3] = 0; + TRACE("planes %d %d %d\n", 0, size, size + size2); + TRACE("strides %d %d %d\n", 0, stride, stride2, stride2); + break; + case PIX_FMT_YUVA420P: + stride = ROUND_UP_4(width); + h2 = ROUND_UP_X(height, pinfo->y_chroma_shift); + size = stride * h2; + w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift); + stride2 = ROUND_UP_4(w2); + h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift); + size2 = stride2 * h2; + fsize = 2 * size + 2 * size2; + if (!encode && !ptr) { + TRACE("allocate a buffer for a decoded picture.\n"); + ptr = av_mallocz(fsize); + if (!ptr) { + ERR("[%d] failed to allocate memory.\n", __LINE__); + return -1; + } + } + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->data[3] = picture->data[2] + size2; + picture->linesize[0] = stride; + picture->linesize[1] = stride2; + picture->linesize[2] = stride2; + picture->linesize[3] = stride; + TRACE("planes %d %d %d\n", 0, size, size + size2); + TRACE("strides %d %d %d\n", 0, stride, stride2, stride2); + break; + case PIX_FMT_RGB24: + case PIX_FMT_BGR24: + stride = ROUND_UP_4 (width * 3); + fsize = stride * height; + TRACE("stride: %d, size: %d\n", stride, fsize); + + if (!encode && !ptr) { + TRACE("allocate a buffer for a decoded picture.\n"); + ptr = av_mallocz(fsize); + if (!ptr) { + ERR("[%d] failed to allocate memory.\n", __LINE__); + return -1; + } + } + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = 0; + picture->linesize[2] = 0; + picture->linesize[3] = 0; + break; + case PIX_FMT_RGB32: + stride = width * 4; + fsize = stride * height; + TRACE("stride: %d, size: %d\n", stride, fsize); + + if (!encode && !ptr) { + TRACE("allocate a buffer for a decoded picture.\n"); + ptr = av_mallocz(fsize); + if (!ptr) { + ERR("[%d] failed to allocate memory.\n", __LINE__); + return -1; + } + } + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = 0; + picture->linesize[2] = 0; + picture->linesize[3] = 0; + break; + case PIX_FMT_RGB555: + case PIX_FMT_RGB565: + stride = ROUND_UP_4 (width * 2); + fsize = stride * height; + TRACE("stride: %d, size: %d\n", stride, fsize); + + if (!encode && !ptr) { + TRACE("allocate a buffer for a decoded picture.\n"); + ptr = av_mallocz(fsize); + if (!ptr) { + ERR("[%d] failed to allocate memory.\n", __LINE__); + return -1; + } + } + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = 0; + picture->linesize[2] = 0; + picture->linesize[3] = 0; + break; + case PIX_FMT_PAL8: + stride = ROUND_UP_4(width); + size = stride * height; + fsize = size + 256 * 4; + TRACE("stride: %d, size: %d\n", stride, fsize); + + if (!encode && !ptr) { + TRACE("allocate a buffer for a decoded picture.\n"); + ptr = av_mallocz(fsize); + if (!ptr) { + ERR("[%d] failed to allocate memory.\n", __LINE__); + return -1; + } + } + picture->data[0] = ptr; + picture->data[1] = ptr + size; + picture->data[2] = NULL; + picture->data[3] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = 4; + picture->linesize[2] = 0; + picture->linesize[3] = 0; + break; + default: + picture->data[0] = NULL; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + fsize = -1; + ERR("pixel format: %d was wrong.\n", pix_fmt); + break; + } + + return fsize; +} + +static int maru_brill_codec_query_list (MaruBrillCodecState *s) +{ + AVCodec *codec = NULL; + uint32_t size = 0, mem_size = 0; + uint32_t data_len = 0, length = 0; + int32_t codec_type, media_type; + int32_t codec_fmts[4], i; + + /* register avcodec */ + TRACE("register avcodec\n"); + av_register_all(); + + codec = av_codec_next(NULL); + if (!codec) { + ERR("failed to get codec info.\n"); + return -1; + } + + // a region to store the number of codecs. + length = 32 + 64 + 6 * sizeof(int32_t); + mem_size = size = sizeof(uint32_t); + + while (codec) { + codec_type = + codec->decode ? CODEC_TYPE_DECODE : CODEC_TYPE_ENCODE; + media_type = codec->type; + + memset(codec_fmts, -1, sizeof(codec_fmts)); + if (media_type == AVMEDIA_TYPE_VIDEO) { + if (codec->pix_fmts) { + for (i = 0; codec->pix_fmts[i] != -1; i++) { + codec_fmts[i] = codec->pix_fmts[i]; + } + } + } else if (media_type == AVMEDIA_TYPE_AUDIO) { + if (codec->sample_fmts) { + for (i = 0; codec->sample_fmts[i] != -1; i++) { + codec_fmts[i] = codec->sample_fmts[i]; + } + } + } else { + ERR("%s of media type is unknown.\n", codec->name); + } + + memset(s->vaddr + mem_size, 0x00, length); + mem_size += length; + + data_len += length; + memcpy(s->vaddr, &data_len, sizeof(data_len)); + + memcpy(s->vaddr + size, &codec_type, sizeof(codec_type)); + size += sizeof(codec_type); + memcpy(s->vaddr + size, &media_type, sizeof(media_type)); + size += sizeof(media_type); + memcpy(s->vaddr + size, codec->name, strlen(codec->name)); + size += 32; + memcpy(s->vaddr + size, + codec->long_name, strlen(codec->long_name)); + size += 64; + memcpy(s->vaddr + size, codec_fmts, sizeof(codec_fmts)); + size += sizeof(codec_fmts); + + codec = av_codec_next(codec); + } + + return 0; +} + +static int maru_brill_codec_get_context_index(MaruBrillCodecState *s) +{ + int index; + + TRACE("enter: %s\n", __func__); + + for (index = 1; index < CODEC_CONTEXT_MAX; index++) { + if (s->context[index].occupied == false) { + TRACE("get %d of codec context successfully.\n", index); + s->context[index].occupied = true; + break; + } + } + + if (index == CODEC_CONTEXT_MAX) { + ERR("failed to get available codec context. "); + ERR("try to run codec again.\n"); + index = -1; + } + + TRACE("leave: %s\n", __func__); + + return index; +} + +// allocate avcontext and avframe struct. +static AVCodecContext *maru_brill_codec_alloc_context(MaruBrillCodecState *s, int index) +{ + TRACE("enter: %s\n", __func__); + + TRACE("allocate %d of context and frame.\n", index); + s->context[index].avctx = avcodec_alloc_context(); + s->context[index].frame = avcodec_alloc_frame(); + s->context[index].opened = false; + + s->context[index].parser_buf = NULL; + s->context[index].parser_use = false; + + TRACE("leave: %s\n", __func__); + + return s->context[index].avctx; +} + +static AVCodec *maru_brill_codec_find_avcodec(uint8_t *mem_buf) +{ + AVCodec *codec = NULL; + int32_t encode, size = 0; + char codec_name[32] = {0, }; + + memcpy(&encode, mem_buf, sizeof(encode)); + size = sizeof(encode); + memcpy(codec_name, mem_buf + size, sizeof(codec_name)); + size += sizeof(codec_name); + + TRACE("type: %d, name: %s\n", encode, codec_name); + + if (encode) { + codec = avcodec_find_encoder_by_name (codec_name); + } else { + codec = avcodec_find_decoder_by_name (codec_name); + } + INFO("%s!! find %s %s\n", + codec ? "success" : "failure", + codec_name, encode ? "encoder" : "decoder"); + + return codec; +} + +static void read_codec_init_data(AVCodecContext *avctx, uint8_t *mem_buf) +{ + struct video_data video = { 0, }; + struct audio_data audio = { 0, }; + int bitrate = 0, size = 0; + + memcpy(&video, mem_buf + size, sizeof(video)); + size = sizeof(video); + serialize_video_data(&video, avctx); + + memcpy(&audio, mem_buf + size, sizeof(int32_t) * 6); + size += sizeof(int32_t) * 6; + memcpy(&audio.bits_per_smp_fmt, mem_buf + size, sizeof(int32_t)); + size += sizeof(int32_t); + memcpy(&audio.channel_layout, mem_buf + size, sizeof(int64_t)); + size += sizeof(int64_t); + serialize_audio_data(&audio, avctx); + + memcpy(&bitrate, mem_buf + size, sizeof(bitrate)); + size += sizeof(bitrate); + if (bitrate) { + avctx->bit_rate = bitrate; + } + memcpy(&avctx->codec_tag, mem_buf + size, sizeof(avctx->codec_tag)); + size += sizeof(avctx->codec_tag); + memcpy(&avctx->extradata_size, + mem_buf + size, sizeof(avctx->extradata_size)); + size += sizeof(avctx->extradata_size); + if (avctx->extradata_size > 0) { + TRACE("extradata size: %d.\n", avctx->extradata_size); + avctx->extradata = + av_mallocz(ROUND_UP_X(avctx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE, 4)); + if (avctx->extradata) { + memcpy(avctx->extradata, mem_buf + size, avctx->extradata_size); + } + } else { + TRACE("no extra data.\n"); + avctx->extradata = + av_mallocz(ROUND_UP_X(FF_INPUT_BUFFER_PADDING_SIZE, 4)); + } +} + +// write the result of codec_init +static void write_codec_init_data(AVCodecContext *avctx, uint8_t *mem_buf) +{ + int size = 0; + + if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { + int osize = 0; + + TRACE("codec_init. audio sample_fmt: %d\n", avctx->sample_fmt); + + memcpy(mem_buf, &avctx->sample_fmt, sizeof(avctx->sample_fmt)); + size = sizeof(avctx->sample_fmt); + memcpy(mem_buf + size, + &avctx->frame_size, sizeof(avctx->frame_size)); + size += sizeof(avctx->frame_size); + osize = av_get_bits_per_sample(avctx->codec->id) / 8; + memcpy(mem_buf + size, &osize, sizeof(osize)); + } +} + +// write the result of codec_decode_video +static void write_codec_decode_video_data(AVCodecContext *avctx, int len, + int got_pic_ptr, uint8_t *mem_buf) +{ + struct video_data video; + int size = 0; + + memcpy(mem_buf, &len, sizeof(len)); + size = sizeof(len); + memcpy(mem_buf + size, &got_pic_ptr, sizeof(got_pic_ptr)); + size += sizeof(got_pic_ptr); + if (avctx) { + deserialize_video_data(avctx, &video); + memcpy(mem_buf + size, &video, sizeof(struct video_data)); + } +} + +// write the result of codec_decode_audio +static void write_codec_decode_audio_data(int sample_rate, int channel, + int64_t channel_layout, int len, + int frame_size_ptr, uint8_t *mem_buf) +{ + int size = 0; + + TRACE("copy decode_audio. len %d, frame_size %d\n", len, frame_size_ptr); + + memcpy(mem_buf, &sample_rate, sizeof(sample_rate)); + size = sizeof(sample_rate); + memcpy(mem_buf + size, &channel, sizeof(channel)); + size += sizeof(channel); + memcpy(mem_buf + size, &channel_layout, sizeof(channel_layout)); + size += sizeof(channel_layout); + memcpy(mem_buf + size, &len, sizeof(len)); + size += sizeof(len); + memcpy(mem_buf + size, &frame_size_ptr, sizeof(frame_size_ptr)); +} + +// codec functions +static bool codec_init(MaruBrillCodecState *s, int ctx_id, int f_id, void *elem) +{ + AVCodecContext *avctx = NULL; + AVCodec *codec = NULL; + int size = 0, ret = -1; + uint8_t *meta_buf = NULL; + + TRACE("enter: %s\n", __func__); + + // assign meta_buf + meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE); + meta_buf += 8; // skipped header. + + // allocate AVCodecContext + avctx = maru_brill_codec_alloc_context(s, ctx_id); + if (!avctx) { + ERR("[%d] failed to allocate context.\n", __LINE__); + ret = -1; + } else { + s->context[ctx_id].file_index = f_id; + + codec = maru_brill_codec_find_avcodec(meta_buf); + if (codec) { + size = sizeof(int32_t) + 32; // buffer size of codec_name + read_codec_init_data(avctx, meta_buf + size); + + ret = avcodec_open(avctx, codec); + INFO("avcodec_open done. ctx_id: %d\n", ctx_id); + + s->context[ctx_id].opened = true; + s->context[ctx_id].parser_ctx = + maru_brill_codec_parser_init(avctx); + } else { + ERR("failed to find codec. ctx_id: %d\n", ctx_id); + } + } + + // return the result of avcodec_open + memcpy(meta_buf, &ret, sizeof(ret)); + size = sizeof(ret); + if (ret < 0) { + ERR("failed to open codec contex.\n"); + } else { + write_codec_init_data(avctx, meta_buf + size); + } + + maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id, f_id); + + TRACE("leave: %s\n", __func__); + + return true; +} + +static bool codec_deinit(MaruBrillCodecState *s, int ctx_id, int f_id, void *data_buf) +{ + AVCodecContext *avctx = NULL; + AVFrame *frame = NULL; + AVCodecParserContext *parserctx = NULL; + + TRACE("enter: %s\n", __func__); + + avctx = s->context[ctx_id].avctx; + frame = s->context[ctx_id].frame; + parserctx = s->context[ctx_id].parser_ctx; + if (!avctx || !frame) { + TRACE("%d of AVCodecContext or AVFrame is NULL. " + " Those resources have been released before.\n", ctx_id); + return false; + } else { + qemu_mutex_lock(&s->threadpool.mutex); + if (!s->context[ctx_id].opened) { + TRACE("%d of context has already been closed\n", ctx_id); + qemu_mutex_unlock(&s->threadpool.mutex); + return false; + } + avcodec_close(avctx); + INFO("close avcontext of %d\n", ctx_id); + s->context[ctx_id].opened = false; + qemu_mutex_unlock(&s->threadpool.mutex); + + if (avctx->extradata) { + TRACE("free context extradata\n"); + av_free(avctx->extradata); + s->context[ctx_id].avctx->extradata = NULL; + } + + if (avctx->palctrl) { + TRACE("free context palctrl \n"); + av_free(avctx->palctrl); + s->context[ctx_id].avctx->palctrl = NULL; + } + + if (frame) { + TRACE("free frame\n"); + av_free(frame); + s->context[ctx_id].frame = NULL; + } + + if (avctx) { + TRACE("free codec context\n"); + av_free(avctx); + s->context[ctx_id].avctx = NULL; + } + + if (parserctx) { + av_parser_close(parserctx); + s->context[ctx_id].parser_ctx = NULL; + } + } + + TRACE("leave: %s\n", __func__); + + return true; +} + +// +static bool codec_flush_buffers(MaruBrillCodecState *s, int ctx_id, int f_id, void *data_buf) +{ + AVCodecContext *avctx = NULL; + + TRACE("enter: %s\n", __func__); + + avctx = s->context[ctx_id].avctx; + if (!avctx) { + ERR("%d of AVCodecContext is NULL.\n", ctx_id); + return false; + } else { + avcodec_flush_buffers(avctx); + TRACE("flush %d context of buffers.\n", ctx_id); + } + + TRACE("leave: %s\n", __func__); + + return true; +} + +static bool codec_decode_video(MaruBrillCodecState *s, int ctx_id, int f_id, void *data_buf) +{ + AVCodecContext *avctx = NULL; + AVFrame *picture = NULL; + AVPacket avpkt; + int got_pic_ptr = 0, len = 0; + uint8_t *inbuf = NULL; + int inbuf_size, idx, size = 0; + int64_t in_offset; + + DeviceMemEntry *elem = NULL; + uint8_t *meta_buf = NULL; + + TRACE("enter: %s\n", __func__); + + meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE); + meta_buf += 8; // skipped header. + + memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size)); + size = sizeof(inbuf_size); + memcpy(&idx, meta_buf + size, sizeof(idx)); + size += sizeof(idx); + memcpy(&in_offset, meta_buf + size, sizeof(in_offset)); + size += sizeof(in_offset); + TRACE("decode_video. input buffer size: %d\n", inbuf_size); + + elem = (DeviceMemEntry *)data_buf; + if (elem && elem->buf) { + inbuf = elem->buf; + } else if (elem) { + inbuf_size = 0; + TRACE("decode_video. no input buffer. ctx_id: %d, %p, %d\n", + ctx_id, inbuf, elem->buf_size); + } else { + ERR("wrong input data\n"); + return false; + } + + av_init_packet(&avpkt); + avpkt.data = inbuf; + avpkt.size = inbuf_size; + + avctx = s->context[ctx_id].avctx; + picture = s->context[ctx_id].frame; + if (!avctx || !picture) { + ERR("%d of AVCodecContext or AVFrame is NULL.\n", ctx_id); + len = -1; + } else if (!avctx->codec) { + ERR("%d of AVCodec is NULL.\n", ctx_id); + len = -1; + } else { + // in case of skipping frames + picture->pict_type = -1; + + len = avcodec_decode_video2(avctx, picture, &got_pic_ptr, &avpkt); + if (len < 0) { + ERR("failed to decode video. ctx index: %d\n", ctx_id); + } + } + + TRACE("after decoding video. len: %d, have_data: %d\n", + len, got_pic_ptr); + + write_codec_decode_video_data(avctx, len, got_pic_ptr, meta_buf); + maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id, f_id); + + TRACE("leave: %s\n", __func__); + + return true; +} + +static bool codec_picture_copy (MaruBrillCodecState *s, int ctx_id, int f_id, void *elem) +{ + AVCodecContext *avctx; + AVPicture *src; + AVPicture dst; + uint8_t *out_buffer = NULL, *tempbuf = NULL; + int pict_size = 0; + + TRACE("enter: %s\n", __func__); + + TRACE("copy decoded image of %d context.\n", ctx_id); + + avctx = s->context[ctx_id].avctx; + src = (AVPicture *)s->context[ctx_id].frame; + if (!avctx || !src) { + ERR("%d of AVCodecContext or AVFrame is NULL.\n", ctx_id); + } else if (!avctx->codec) { + ERR("%d of AVCodec is NULL.\n", ctx_id); + } else { + TRACE("decoded image. pix_fmt: %d width: %d, height: %d\n", + avctx->pix_fmt, avctx->width, avctx->height); + + pict_size = + maru_brill_codec_get_picture_size(&dst, NULL, avctx->pix_fmt, + avctx->width, avctx->height, false); + if ((pict_size) < 0) { + ERR("picture size: %d\n", pict_size); + } else { + TRACE("picture size: %d\n", pict_size); + av_picture_copy(&dst, src, avctx->pix_fmt, + avctx->width, avctx->height); + + tempbuf = g_malloc0(pict_size); + if (!tempbuf) { + ERR("failed to allocate a picture buffer. size: %d\n", pict_size); + } else { + out_buffer = dst.data[0]; + memcpy(tempbuf, out_buffer, pict_size); + } + av_free(out_buffer); + } + } + maru_brill_codec_push_writequeue(s, tempbuf, pict_size, ctx_id, f_id); + + TRACE("leave: %s\n", __func__); + + return true; +} + +static bool codec_decode_audio(MaruBrillCodecState *s, int ctx_id, int f_id, void *data_buf) +{ + AVCodecContext *avctx; + AVPacket avpkt; + int16_t *samples = NULL; + uint8_t *inbuf = NULL; + int inbuf_size = 0; + int len = 0, frame_size_ptr = 0; + uint8_t *meta_buf = NULL; + DeviceMemEntry *elem = NULL; + uint8_t *tempbuf = NULL; + + TRACE("enter: %s\n", __func__); + + meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE); + meta_buf += 8; // skipped header. + + memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size)); + TRACE("before decoding audio. inbuf_size: %d\n", inbuf_size); + + elem = (DeviceMemEntry *)data_buf; + if (elem && elem->buf) { + inbuf = elem->buf; + } else if (elem) { + inbuf_size = 0; + TRACE("decode_audio. no input buffer.\n"); + } else { + ERR("wrong input data\n"); + return false; + } + + av_init_packet(&avpkt); + avpkt.data = inbuf; + avpkt.size = inbuf_size; + + avctx = s->context[ctx_id].avctx; + if (!avctx) { + ERR("[%s] %d of AVCodecContext is NULL!\n", __func__, ctx_id); + write_codec_decode_audio_data(0, 0, 0, -1, 0, meta_buf); + } else if (!avctx->codec) { + ERR("%d of AVCodec is NULL.\n", ctx_id); + write_codec_decode_audio_data(0, 0, 0, -1, 0, meta_buf); + } else { + frame_size_ptr = AVCODEC_MAX_AUDIO_FRAME_SIZE; + samples = av_mallocz(frame_size_ptr); + if (!samples) { + ERR("failed to allocate an outbuf of audio.\n"); + len = -1; + } else { + len = + avcodec_decode_audio3(avctx, samples, &frame_size_ptr, &avpkt); + + TRACE("audio. len %d, channel_layout %lld, frame_size %d\n", + len, avctx->channel_layout, frame_size_ptr); + } + + write_codec_decode_audio_data(avctx->sample_rate, avctx->channels, + avctx->channel_layout, len, + frame_size_ptr, meta_buf); + } + + if (len < 0) { + ERR("failed to decode audio. ctx_id: %d, len: %d\n", ctx_id, len); + frame_size_ptr = 0; + } else { + if (frame_size_ptr > 0) { + tempbuf = g_malloc0(frame_size_ptr); + if (!tempbuf) { + ERR("failed to allocate decoded audio buffer. " + "ctx_id: %d, outbuf_size: %d\n", ctx_id, frame_size_ptr); + } else { + memcpy(tempbuf, samples, frame_size_ptr); + } + av_free(samples); + } + } + + maru_brill_codec_push_writequeue(s, tempbuf, frame_size_ptr, ctx_id, f_id); + + TRACE("leave: %s\n", __func__); + + return true; +} + +static bool codec_encode_video(MaruBrillCodecState *s, int ctx_id, int f_id, void *data_buf) +{ + AVCodecContext *avctx = NULL; + AVFrame *pict = NULL; + uint8_t *inbuf = NULL, *outbuf = NULL; + int inbuf_size, outbuf_size, len = 0; + int ret; + int64_t in_timestamp; + + uint8_t *meta_buf = NULL; + DeviceMemEntry *elem = NULL; + uint8_t *tempbuf = NULL; + + TRACE("enter: %s\n", __func__); + + meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE); + meta_buf += 8; // skipped header. + + memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size)); + memcpy(&in_timestamp, meta_buf + sizeof(inbuf_size), sizeof(in_timestamp)); + TRACE("input buffer size: %d\n", inbuf_size); + + elem = (DeviceMemEntry *)data_buf; + if (elem && elem->buf) { + inbuf = elem->buf; + } else if (elem) { + TRACE("encode_video. no input buffer.\n"); + inbuf_size = 0; + } else { + ERR("wrong input data\n"); + return false; + } + + avctx = s->context[ctx_id].avctx; + pict = s->context[ctx_id].frame; + if (!avctx || !pict) { + ERR("%d of context or frame is NULL\n", ctx_id); + len = -1; + } else if (!avctx->codec) { + ERR("%d of AVCodec is NULL.\n", ctx_id); + len = -1; + } else { + TRACE("pixel format: %d inbuf: %p, picture data: %p\n", + avctx->pix_fmt, inbuf, pict->data[0]); + + ret = + maru_brill_codec_get_picture_size((AVPicture *)pict, inbuf, + avctx->pix_fmt, avctx->width, + avctx->height, true); + if (ret < 0) { + ERR("after avpicture_fill, ret:%d\n", ret); + len = -1; + } else { + if (avctx->time_base.num == 0) { + pict->pts = AV_NOPTS_VALUE; + } else { + AVRational bq = + {1, (G_USEC_PER_SEC * G_GINT64_CONSTANT(1000))}; + pict->pts = av_rescale_q(in_timestamp, bq, avctx->time_base); + } + TRACE("before encode video, ticks_per_frame:%d, pts:%lld\n", + avctx->ticks_per_frame, pict->pts); + + outbuf_size = + (avctx->width * avctx->height * 6) + FF_MIN_BUFFER_SIZE; + outbuf = g_malloc0(outbuf_size); + if (!outbuf) { + ERR("failed to allocate a buffer of encoding video.\n"); + len = -1; + } else { + len = avcodec_encode_video(avctx, outbuf, outbuf_size, pict); + + TRACE("encode video! len:%d pts:%lld outbuf:%p outbuf size: %d\n", + len, pict->pts, outbuf, outbuf_size); + } + } + } + + // write encoded video data + memcpy(meta_buf, &len, sizeof(len)); + if (len < 0) { + ERR("failed to encode video. len: %d\n", len); + } else { + tempbuf = g_malloc0(len); + if (!tempbuf) { + ERR("failed to allocate an element of writequeue.\n"); + } else { + memcpy(tempbuf, outbuf, len); + } + } + + if (outbuf) { + TRACE("release encoded output buffer. %p\n", outbuf); + g_free(outbuf); + } + + maru_brill_codec_push_writequeue(s, tempbuf, len, ctx_id, f_id); + + TRACE("leave: %s\n", __func__); + return true; +} + +static bool codec_encode_audio(MaruBrillCodecState *s, int ctx_id, int f_id, void *data_buf) +{ + AVCodecContext *avctx; + uint8_t *inbuf = NULL, *outbuf = NULL; + int32_t inbuf_size, max_size; + int len = 0; + uint8_t *meta_buf = NULL; + + DeviceMemEntry *elem = NULL; + uint8_t *tempbuf = NULL; + + TRACE("enter: %s\n", __func__); + + meta_buf = s->vaddr + ((ctx_id - 1) * CODEC_META_DATA_SIZE); + meta_buf += 8; // skipped header. + + memcpy(&inbuf_size, meta_buf, sizeof(inbuf_size)); + memcpy(&max_size, meta_buf + sizeof(inbuf_size), sizeof(max_size)); + TRACE("encoding audio. in_size: %d, max_size: %d\n", inbuf_size, max_size); + + elem = (DeviceMemEntry *)data_buf; + if (elem && elem->buf) { + inbuf = elem->buf; + } else if (elem) { + TRACE("no input buffer to encode audio.\n"); + inbuf_size = 0; + } else { + ERR("wrong input data\n"); + return false; + } + + avctx = s->context[ctx_id].avctx; + if (!avctx) { + ERR("[%s] %d of Context is NULL!\n", __func__, ctx_id); + } else if (!avctx->codec) { + ERR("%d of AVCodec is NULL.\n", ctx_id); + } else { + outbuf = g_malloc0(max_size + FF_MIN_BUFFER_SIZE); + if (!outbuf) { + ERR("failed to allocate a buffer of encoding audio.\n"); + len = -1; + } else { + len = + avcodec_encode_audio(avctx, outbuf, max_size, (short *)inbuf); + TRACE("after encoding audio. len: %d\n", len); + } + } + + // write encoded audio data + memcpy(meta_buf, &len, sizeof(len)); + if (len < 0) { + ERR("failed to encode audio. ctx_id: %d len: %d\n", ctx_id, len); + } else { + tempbuf = g_malloc0(len); + if (!tempbuf) { + ERR("encode_audio. failed to allocate temporary buffer.\n"); + } else { + memcpy(tempbuf, outbuf, len); + } + } + + if (outbuf) { + av_free(outbuf); + } + + maru_brill_codec_push_writequeue(s, tempbuf, len, ctx_id, f_id); + + TRACE("[%s] leave:\n", __func__); + return true; +} + +static AVCodecParserContext *maru_brill_codec_parser_init(AVCodecContext *avctx) +{ + AVCodecParserContext *parser = NULL; + + if (!avctx) { + ERR("context is NULL\n"); + return NULL; + } + + switch (avctx->codec_id) { + case CODEC_ID_MPEG4: + case CODEC_ID_VC1: + TRACE("not using parser.\n"); + break; + case CODEC_ID_H264: + if (avctx->extradata_size == 0) { + TRACE("H.264 with no extradata, creating parser.\n"); + parser = av_parser_init (avctx->codec_id); + } + break; + default: + parser = av_parser_init (avctx->codec_id); + if (parser) { + INFO("using parser. %d\n", avctx->codec_id); + } + break; + } + + return parser; +} + +// +static void maru_brill_codec_bh_callback(void *opaque) +{ + MaruBrillCodecState *s = (MaruBrillCodecState *)opaque; + + TRACE("enter: %s\n", __func__); + + qemu_mutex_lock(&s->context_queue_mutex); + if (!QTAILQ_EMPTY(&codec_wq)) { + qemu_mutex_unlock(&s->context_queue_mutex); + + TRACE("raise irq\n"); + qemu_irq_raise(s->dev.irq[0]); + irq_raised = 1; + } else { + qemu_mutex_unlock(&s->context_queue_mutex); + TRACE("codec_wq is empty!!\n"); + } + + TRACE("leave: %s\n", __func__); +} + +/* + * Codec Device APIs + */ +static uint64_t maru_brill_codec_read(void *opaque, + target_phys_addr_t addr, + unsigned size) +{ + MaruBrillCodecState *s = (MaruBrillCodecState *)opaque; + uint64_t ret = 0; + + switch (addr) { + case CODEC_CMD_GET_THREAD_STATE: +#if 0 + if (s->thread_state) { + s->thread_state = CODEC_TASK_START; + + qemu_mutex_lock(&s->context_queue_mutex); + if (!QTAILQ_EMPTY(&codec_wq)) { + ret = CODEC_TASK_END; + } + qemu_mutex_unlock(&s->context_queue_mutex); + } +#endif + qemu_mutex_lock(&s->context_queue_mutex); + if (irq_raised) { + ret = CODEC_TASK_END; + qemu_irq_lower(s->dev.irq[0]); + irq_raised = 0; + } + qemu_mutex_unlock(&s->context_queue_mutex); + + TRACE("get thread_state. ret: %d\n", ret); + break; + + case CODEC_CMD_GET_CTX_FROM_QUEUE: + { + DeviceMemEntry *head = NULL; + + qemu_mutex_lock(&s->context_queue_mutex); + head = QTAILQ_FIRST(&codec_wq); + if (head) { + ret = head->ctx_id; + QTAILQ_REMOVE(&codec_wq, head, node); + entry[ret] = head; + TRACE("get a elem from codec_wq. 0x%x\n", head); + } else { + ret = 0; + } + qemu_mutex_unlock(&s->context_queue_mutex); + + TRACE("get a head from a writequeue. head: %x\n", ret); + } + break; + + case CODEC_CMD_GET_VERSION: + ret = CODEC_VERSION; + TRACE("codec version: %d\n", ret); + break; + + case CODEC_CMD_GET_ELEMENT: + ret = maru_brill_codec_query_list(s); + break; + + case CODEC_CMD_GET_CONTEXT_INDEX: + ret = maru_brill_codec_get_context_index(s); + TRACE("get context index: %d\n", ret); + break; + + default: + ERR("no avaiable command for read. %d\n", addr); + } + + return ret; +} + +static void maru_brill_codec_write(void *opaque, target_phys_addr_t addr, + uint64_t value, unsigned size) +{ + MaruBrillCodecState *s = (MaruBrillCodecState *)opaque; + + switch (addr) { + case CODEC_CMD_API_INDEX: + TRACE("set codec_cmd value: %d\n", value); + s->ioparam.api_index = value; + maru_brill_codec_wakeup_threads(s, value); + break; + + case CODEC_CMD_CONTEXT_INDEX: + TRACE("set context_index value: %d\n", value); + s->ioparam.ctx_index = value; + break; + + case CODEC_CMD_FILE_INDEX: + TRACE("set file_index value: 0x%x\n", value); + s->ioparam.file_index = value; + break; + + case CODEC_CMD_DEVICE_MEM_OFFSET: + TRACE("set mem_offset value: 0x%x\n", value); + s->ioparam.mem_offset = value; + break; + + case CODEC_CMD_RELEASE_CONTEXT: + maru_brill_codec_release_context(s, (int32_t)value); + break; + + case CODEC_CMD_GET_DATA_FROM_QUEUE: + maru_brill_codec_pop_writequeue(s, (uint32_t)value); + break; + + default: + ERR("no available command for write. %d\n", addr); + } +} + +static const MemoryRegionOps maru_brill_codec_mmio_ops = { + .read = maru_brill_codec_read, + .write = maru_brill_codec_write, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false + }, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static int maru_brill_codec_initfn(PCIDevice *dev) +{ + MaruBrillCodecState *s = DO_UPCAST(MaruBrillCodecState, dev, dev); + uint8_t *pci_conf = s->dev.config; + + INFO("device initialization.\n"); + memset(&s->ioparam, 0, sizeof(CodecParam)); + + qemu_mutex_init(&s->context_mutex); + qemu_mutex_init(&s->context_queue_mutex); + qemu_mutex_init(&s->ioparam_queue_mutex); + + maru_brill_codec_get_cpu_cores(); + maru_brill_codec_threads_create(s); + + maru_brill_codec_pixfmt_info_init(); + + // register a function to qemu bottom-halves to switch context. + s->codec_bh = qemu_bh_new(maru_brill_codec_bh_callback, s); + + pci_config_set_interrupt_pin(pci_conf, 1); + + memory_region_init_ram(&s->vram, "maru_brill_codec.vram", CODEC_MEM_SIZE); + s->vaddr = (uint8_t *)memory_region_get_ram_ptr(&s->vram); + + memory_region_init_io(&s->mmio, &maru_brill_codec_mmio_ops, s, + "maru_brill_codec.mmio", CODEC_REG_SIZE); + + pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); + pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); + + return 0; +} + +static void maru_brill_codec_exitfn(PCIDevice *dev) +{ + MaruBrillCodecState *s = DO_UPCAST(MaruBrillCodecState, dev, dev); + INFO("device exit\n"); + + qemu_mutex_destroy(&s->context_mutex); + qemu_mutex_destroy(&s->context_queue_mutex); + qemu_mutex_destroy(&s->ioparam_queue_mutex); + + qemu_bh_delete(s->codec_bh); + + memory_region_destroy(&s->vram); + memory_region_destroy(&s->mmio); +} + +static void maru_brill_codec_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = maru_brill_codec_initfn; + k->exit = maru_brill_codec_exitfn; + k->vendor_id = PCI_VENDOR_ID_TIZEN; + k->device_id = PCI_DEVICE_ID_VIRTUAL_BRILL_CODEC; + k->class_id = PCI_CLASS_OTHERS; + dc->desc = "Virtual new codec device for Tizen emulator"; +} + +static TypeInfo codec_device_info = { + .name = CODEC_DEVICE_NAME, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(MaruBrillCodecState), + .class_init = maru_brill_codec_class_init, +}; + +static void codec_register_types(void) +{ + type_register_static(&codec_device_info); +} + +type_init(codec_register_types) + +int maru_brill_codec_pci_device_init(PCIBus *bus) +{ + INFO("device create.\n"); + pci_create_simple(bus, -1, CODEC_DEVICE_NAME); + return 0; +} diff --git a/tizen/src/hw/maru_brill_codec.h b/tizen/src/hw/maru_brill_codec.h new file mode 100644 index 0000000000..306841a6bd --- /dev/null +++ b/tizen/src/hw/maru_brill_codec.h @@ -0,0 +1,158 @@ +/* + * Virtual Codec device + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Kitae Kim + * SeokYeon Hwang + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include + +#include "hw.h" +#include "kvm.h" +#include "pci.h" +#include "pci_ids.h" +#include "osutil.h" +#include "qemu-common.h" +#include "qemu-thread.h" + +#include "libavformat/avformat.h" +#include "maru_device_ids.h" +#include "tizen/src/debug_ch.h" + +#define CODEC_CONTEXT_MAX 1024 + +/* + * Codec Device Structures + */ +typedef struct CodecParam { + int32_t api_index; + int32_t ctx_index; + uint32_t file_index; + uint32_t mem_offset; +} CodecParam; + +struct video_data { + int32_t width; + int32_t height; + int32_t fps_n; + int32_t fps_d; + int32_t par_n; + int32_t par_d; + int32_t pix_fmt; + int32_t bpp; + int32_t ticks_per_frame; +}; + +struct audio_data { + int32_t channels; + int32_t sample_rate; + int32_t block_align; + int32_t depth; + int32_t sample_fmt; + int32_t frame_size; + int32_t bits_per_smp_fmt; + int64_t channel_layout; +}; + +typedef struct CodecContext { + AVCodecContext *avctx; + AVFrame *frame; + AVCodecParserContext *parser_ctx; + uint8_t *parser_buf; + uint16_t parser_use; + uint16_t occupied; + uint32_t file_index; + bool opened; +} CodecContext; + +typedef struct CodecThreadPool { + QemuThread *threads; + QemuMutex mutex; + QemuCond cond; +} CodecThreadPool; + + +typedef struct MaruBrillCodecState { + PCIDevice dev; + + uint8_t *vaddr; + MemoryRegion vram; + MemoryRegion mmio; + + QEMUBH *codec_bh; + QemuMutex context_mutex; + QemuMutex context_queue_mutex; + QemuMutex ioparam_queue_mutex; + + CodecThreadPool threadpool; + uint32_t thread_state; + uint8_t is_thread_running; + + CodecContext context[CODEC_CONTEXT_MAX]; + CodecParam ioparam; +} MaruBrillCodecState; + +enum codec_io_cmd { + CODEC_CMD_API_INDEX = 0x28, + CODEC_CMD_CONTEXT_INDEX = 0x2C, + CODEC_CMD_FILE_INDEX = 0x30, + CODEC_CMD_DEVICE_MEM_OFFSET = 0x34, + CODEC_CMD_GET_THREAD_STATE = 0x38, + CODEC_CMD_GET_CTX_FROM_QUEUE = 0x3C, + CODEC_CMD_GET_DATA_FROM_QUEUE = 0x40, + CODEC_CMD_RELEASE_CONTEXT = 0x44, + CODEC_CMD_GET_VERSION = 0x50, + CODEC_CMD_GET_ELEMENT = 0x54, + CODEC_CMD_GET_CONTEXT_INDEX = 0x58, +}; + +enum codec_api_type { + CODEC_INIT = 0, + CODEC_DECODE_VIDEO, + CODEC_ENCODE_VIDEO, + CODEC_DECODE_AUDIO, + CODEC_ENCODE_AUDIO, + CODEC_PICTURE_COPY, + CODEC_DEINIT, + CODEC_FLUSH_BUFFERS, + }; + +enum codec_type { + CODEC_TYPE_UNKNOWN = -1, + CODEC_TYPE_DECODE, + CODEC_TYPE_ENCODE, +}; + +enum thread_state { + CODEC_TASK_START = 0, + CODEC_TASK_END = 0x1f, +}; + +/* + * Codec Device Functions + */ +int maru_brill_codec_pci_device_init(PCIBus *bus); diff --git a/tizen/src/hw/maru_camera_linux_pci.c b/tizen/src/hw/maru_camera_linux_pci.c index 08cba88089..dfedde0853 100644 --- a/tizen/src/hw/maru_camera_linux_pci.c +++ b/tizen/src/hw/maru_camera_linux_pci.c @@ -81,6 +81,7 @@ static struct marucam_framebuffer *framebuffer; static const char *dev_name = "/dev/video0"; static int v4l2_fd; static int convert_trial; +static int read_trial; static int ready_count; static int timeout_n; @@ -556,7 +557,12 @@ static int read_frame(MaruCamState *state) switch (errno) { case EAGAIN: case EINTR: - ERR("DQBUF error, try again: %s\n", strerror(errno)); + ERR("DQBUF error, try again(trial=%d): %s\n", + read_trial, strerror(errno)); + if (--read_trial == -1) { + ERR("Failed trying to dequeue buffer from device\n"); + return -1; + } return 0; case EIO: ERR("The v4l2_read() met the EIO\n"); @@ -581,6 +587,8 @@ static int read_frame(MaruCamState *state) return 0; } +#define MAX_CONVERT_TRIAL 10 +#define MAX_READ_TRIAL 30 static int __v4l2_streaming(MaruCamState *state) { fd_set fds; @@ -649,9 +657,11 @@ static int __v4l2_streaming(MaruCamState *state) } /* clear the skip count for select time-out */ - if (timeout_n > 0) { - timeout_n = 0; - } + timeout_n = 0; + /* reset the read trial */ + read_trial = MAX_READ_TRIAL; + /* reset the convert trial */ + convert_trial = MAX_CONVERT_TRIAL; return 0; } @@ -671,7 +681,8 @@ static void *marucam_worker_thread(void *thread_param) break; } - convert_trial = 10; + convert_trial = MAX_CONVERT_TRIAL; + read_trial = MAX_READ_TRIAL; ready_count = 0; timeout_n = 0; has_success_frame = 0; @@ -854,6 +865,8 @@ void marucam_device_open(MaruCamState *state) ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, strerror(errno)); + v4l2_close(v4l2_fd); + v4l2_fd = 0; param->errCode = errno; return; } diff --git a/tizen/src/hw/maru_codec.c b/tizen/src/hw/maru_codec.c index ad9797fc69..83c9947ca5 100644 --- a/tizen/src/hw/maru_codec.c +++ b/tizen/src/hw/maru_codec.c @@ -336,9 +336,9 @@ void qemu_reset_codec_info(SVCodecState *s, uint32_t value) for (ctx_idx = 0; ctx_idx < CODEC_CONTEXT_MAX; ctx_idx++) { if (s->codec_ctx[ctx_idx].file_index == value) { TRACE("reset %d context\n", ctx_idx); - qemu_mutex_unlock(&s->thread_mutex); - qemu_av_free(s, ctx_idx); - qemu_mutex_lock(&s->thread_mutex); + qemu_mutex_unlock(&s->thread_mutex); + qemu_av_free(s, ctx_idx); + qemu_mutex_lock(&s->thread_mutex); s->codec_ctx[ctx_idx].avctx_use = false; break; } @@ -398,6 +398,16 @@ static void qemu_init_pix_fmt_info(void) pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2; pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0; + /* JPEG YUV */ + pix_fmt_info[PIX_FMT_YUVJ420P].x_chroma_shift = 1; + pix_fmt_info[PIX_FMT_YUVJ420P].y_chroma_shift = 1; + + pix_fmt_info[PIX_FMT_YUVJ422P].x_chroma_shift = 1; + pix_fmt_info[PIX_FMT_YUVJ422P].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_YUVJ444P].x_chroma_shift = 0; + pix_fmt_info[PIX_FMT_YUVJ444P].y_chroma_shift = 0; + /* RGB formats */ pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0; pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0; @@ -413,6 +423,9 @@ static void qemu_init_pix_fmt_info(void) pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0; pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0; + + pix_fmt_info[PIX_FMT_YUVA420P].x_chroma_shift = 1, + pix_fmt_info[PIX_FMT_YUVA420P].y_chroma_shift = 1; } static uint8_t *qemu_malloc_avpicture (int picture_size) @@ -445,6 +458,9 @@ static int qemu_avpicture_fill(AVPicture *picture, uint8_t *ptr, case PIX_FMT_YUV444P: case PIX_FMT_YUV410P: case PIX_FMT_YUV411P: + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUVJ444P: stride = ROUND_UP_4(width); h2 = ROUND_UP_X(height, pinfo->y_chroma_shift); size = stride * h2; @@ -466,14 +482,39 @@ static int qemu_avpicture_fill(AVPicture *picture, uint8_t *ptr, picture->linesize[1] = stride2; picture->linesize[2] = stride2; picture->linesize[3] = 0; - TRACE("planes %d %d %d", 0, size, size + size2); - TRACE("strides %d %d %d", stride, stride2, stride2); + TRACE("planes %d %d %d\n", 0, size, size + size2); + TRACE("strides %d %d %d\n", stride, stride2, stride2); + break; + case PIX_FMT_YUVA420P: + stride = ROUND_UP_4 (width); + h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); + size = stride * h2; + w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); + stride2 = ROUND_UP_4 (w2); + h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); + size2 = stride2 * h2; + fsize = 2 * size + 2 * size2; + TRACE("stride %d, stride2 %d, size %d, size2 %d, fsize %d\n", + stride, stride2, size, size2, fsize); + if (!encode && !ptr) { + ptr = qemu_malloc_avpicture(fsize); + } + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->data[3] = picture->data[2] + size2; + picture->linesize[0] = stride; + picture->linesize[1] = stride2; + picture->linesize[2] = stride2; + picture->linesize[3] = stride; + TRACE("planes %d %d %d %d\n", 0, size, size + size2, size + 2 * size2); + TRACE("strides %d %d %d %d\n", stride, stride2, stride2, stride); break; case PIX_FMT_RGB24: case PIX_FMT_BGR24: stride = ROUND_UP_4 (width * 3); fsize = stride * height; - TRACE("stride: %d, size: %d\n", stride, fsize); + TRACE("stride: %d, fsize: %d\n", stride, fsize); if (!encode && !ptr) { ptr = qemu_malloc_avpicture(fsize); } @@ -489,7 +530,7 @@ static int qemu_avpicture_fill(AVPicture *picture, uint8_t *ptr, case PIX_FMT_RGB32: stride = width * 4; fsize = stride * height; - TRACE("stride: %d, size: %d\n", stride, fsize); + TRACE("stride: %d, fsize: %d\n", stride, fsize); if (!encode && !ptr) { ptr = qemu_malloc_avpicture(fsize); } @@ -504,9 +545,62 @@ static int qemu_avpicture_fill(AVPicture *picture, uint8_t *ptr, break; case PIX_FMT_RGB555: case PIX_FMT_RGB565: + case PIX_FMT_YUYV422: + case PIX_FMT_UYVY422: stride = ROUND_UP_4 (width * 2); fsize = stride * height; - TRACE("stride: %d, size: %d\n", stride, fsize); + TRACE("stride: %d, fsize: %d\n", stride, fsize); + if (!encode && !ptr) { + ptr = qemu_malloc_avpicture(fsize); + } + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = 0; + picture->linesize[2] = 0; + picture->linesize[3] = 0; + break; + case PIX_FMT_UYYVYY411: + /* FIXME, probably not the right stride */ + stride = ROUND_UP_4 (width); + size = stride * height; + fsize = size + size / 2; + TRACE("stride %d, size %d, fsize %d\n", stride, size, fsize); + if (!encode && !ptr) { + ptr = qemu_malloc_avpicture(fsize); + } + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + picture->linesize[0] = width + width / 2; + picture->linesize[1] = 0; + picture->linesize[2] = 0; + picture->linesize[3] = 0; + break; + case PIX_FMT_GRAY8: + stride = ROUND_UP_4 (width); + fsize = stride * height; + TRACE("stride %d, fsize %d\n", stride, fsize); + if (!encode && !ptr) { + ptr = qemu_malloc_avpicture(fsize); + } + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = 0; + picture->linesize[2] = 0; + picture->linesize[3] = 0; + break; + case PIX_FMT_MONOWHITE: + case PIX_FMT_MONOBLACK: + stride = ROUND_UP_4 ((width + 7) >> 3); + fsize = stride * height; + TRACE("stride %d, fsize %d\n", stride, fsize); if (!encode && !ptr) { ptr = qemu_malloc_avpicture(fsize); } @@ -519,6 +613,24 @@ static int qemu_avpicture_fill(AVPicture *picture, uint8_t *ptr, picture->linesize[2] = 0; picture->linesize[3] = 0; break; + case PIX_FMT_PAL8: + /* already forced to be with stride, so same result as other function */ + stride = ROUND_UP_4 (width); + size = stride * height; + fsize = size + 256 * 4; + TRACE("stride %d, size %d, fsize %d\n", stride, size, fsize); + if (!encode && !ptr) { + ptr = qemu_malloc_avpicture(fsize); + } + picture->data[0] = ptr; + picture->data[1] = ptr + size; /* palette is stored here as 256 32 bit words */ + picture->data[2] = NULL; + picture->data[3] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = 4; + picture->linesize[2] = 0; + picture->linesize[3] = 0; + break; default: picture->data[0] = NULL; picture->data[1] = NULL; @@ -647,7 +759,7 @@ int qemu_avcodec_open(SVCodecState *s) if (codec->type == AVMEDIA_TYPE_AUDIO) { s->codec_ctx[ctx_index].mem_index = s->codec_param.mem_index; TRACE("set mem_index: %d into ctx_index: %d.\n", - s->codec_ctx[ctx_index].mem_index, ctx_index); + s->codec_ctx[ctx_index].mem_index, ctx_index); } #if 0 diff --git a/tizen/src/hw/maru_device_ids.h b/tizen/src/hw/maru_device_ids.h index 8a2a0bd8e9..8e50781b6e 100644 --- a/tizen/src/hw/maru_device_ids.h +++ b/tizen/src/hw/maru_device_ids.h @@ -12,6 +12,7 @@ * SungMin Ha * JiHye Kim * GiWoong Kim + * DaiYoung Kim * YeongKyoon Lee * DongKyun Yun * DoHyung Hong @@ -52,6 +53,7 @@ #define PCI_DEVICE_ID_VIRTIO_KEYBOARD 0x1020 #define PCI_DEVICE_ID_VIRTIO_ESM 0x1024 #define PCI_DEVICE_ID_VIRTIO_HWKEY 0x1028 +#define PCI_DEVICE_ID_VIRTUAL_BRILL_CODEC 0x1040 /* Virtio */ /* diff --git a/tizen/src/hw/maru_virtio_hwkey.c b/tizen/src/hw/maru_virtio_hwkey.c index 29f541b955..f17f4f76c0 100644 --- a/tizen/src/hw/maru_virtio_hwkey.c +++ b/tizen/src/hw/maru_virtio_hwkey.c @@ -37,6 +37,8 @@ MULTI_DEBUG_CHANNEL(qemu, hwkey); #define DEVICE_NAME "virtio-hwkey" +#define MAX_BUF_COUNT 64 +static int vqidx = 0; /* * HW key event queue @@ -69,7 +71,6 @@ typedef struct ElementEntry { QTAILQ_ENTRY(ElementEntry) node; } ElementEntry; -static ElementEntry _elem_buf[10]; static QTAILQ_HEAD(, ElementEntry) elem_queue = QTAILQ_HEAD_INITIALIZER(elem_queue); @@ -77,10 +78,10 @@ static unsigned int elem_ringbuf_cnt; /* _elem_buf */ static unsigned int elem_queue_cnt; /* elem_queue */ VirtIOHwKey *vhk; +VirtQueueElement elem_vhk; /* lock for between communication thread and IO thread */ static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t elem_mutex = PTHREAD_MUTEX_INITIALIZER; void maru_hwkey_event(int event_type, int keycode) { @@ -118,7 +119,6 @@ void maru_hwkey_event(int event_type, int keycode) static void maru_virtio_hwkey_handle(VirtIODevice *vdev, VirtQueue *vq) { int virt_sg_index = 0; - ElementEntry *elem_entry = NULL; TRACE("maru_virtio_hwkey_handle\n"); @@ -126,41 +126,16 @@ static void maru_virtio_hwkey_handle(VirtIODevice *vdev, VirtQueue *vq) TRACE("virtqueue is empty\n"); return; } - - while (true) { - elem_entry = &(_elem_buf[elem_ringbuf_cnt % 10]); - elem_ringbuf_cnt++; - - virt_sg_index = virtqueue_pop(vhk->vq, &elem_entry->elem); - if (virt_sg_index == 0) { - elem_ringbuf_cnt--; - break; - } else if (virt_sg_index < 0) { - ERR("virtqueue is broken\n"); - elem_ringbuf_cnt--; - return; - } - - pthread_mutex_lock(&elem_mutex); - - elem_entry->el_index = ++elem_queue_cnt; - elem_entry->sg_index = (unsigned int)virt_sg_index; - - /* save VirtQueueElement */ - QTAILQ_INSERT_TAIL(&elem_queue, elem_entry, node); - /* call maru_virtio_hwkey_notify */ - qemu_bh_schedule(vhk->bh); - - pthread_mutex_unlock(&elem_mutex); - } + /* Get a queue buffer which is written by guest side. */ + do { + virt_sg_index = virtqueue_pop(vq, &elem_vhk); + TRACE("virtqueue pop.\n"); + } while (virt_sg_index < MAX_BUF_COUNT); } void maru_virtio_hwkey_notify(void) { HwKeyEventEntry *event_entry = NULL; - ElementEntry *elem_entry = NULL; - VirtQueueElement *element = NULL; - void *vbuf = NULL; TRACE("maru_virtio_hwkey_notify\n"); @@ -175,28 +150,22 @@ void maru_virtio_hwkey_notify(void) break; } - elem_entry = QTAILQ_FIRST(&elem_queue); - - if ( elem_entry->sg_index > 0) { - /* get hwkey event from host queue */ - event_entry = QTAILQ_FIRST(&events_queue); + /* get hwkey event from host queue */ + event_entry = QTAILQ_FIRST(&events_queue); - TRACE("hwkey(%d) : keycode=%d, event_type=%d | \ - event_queue_cnt=%d\n", - event_entry->index, + printf("keycode=%d, event_type=%d, event_queue_cnt=%d, vqidx=%d\n", event_entry->hwkey.keycode, event_entry->hwkey.event_type, - event_queue_cnt); + event_queue_cnt, vqidx); - element = &elem_entry->elem; - vbuf = element->in_sg[elem_entry->sg_index - 1].iov_base; - - /* copy event into virtio buffer */ - memcpy(vbuf, &(event_entry->hwkey), sizeof(EmulHwKeyEvent)); - - virtqueue_push(vhk->vq, element, sizeof(EmulHwKeyEvent)); - virtio_notify(&vhk->vdev, vhk->vq); + /* copy event into virtio buffer */ + memcpy(elem_vhk.in_sg[vqidx++].iov_base, &(event_entry->hwkey), sizeof(EmulHwKeyEvent)); + if (vqidx == MAX_BUF_COUNT) { + vqidx = 0; } + virtqueue_push(vhk->vq, &elem_vhk, sizeof(EmulHwKeyEvent)); + virtio_notify(&vhk->vdev, vhk->vq); + pthread_mutex_lock(&event_mutex); /* remove host event */ @@ -222,6 +191,7 @@ static void maru_hwkey_bh(void *opaque) VirtIODevice *maru_virtio_hwkey_init(DeviceState *dev) { INFO("initialize the hwkey device\n"); + vqidx = 0; vhk = (VirtIOHwKey *)virtio_common_init(DEVICE_NAME, VIRTIO_ID_HWKEY, 0 /*config_size*/, sizeof(VirtIOHwKey)); @@ -232,7 +202,7 @@ VirtIODevice *maru_virtio_hwkey_init(DeviceState *dev) } vhk->vdev.get_features = virtio_hwkey_get_features; - vhk->vq = virtio_add_queue(&vhk->vdev, 64, maru_virtio_hwkey_handle); + vhk->vq = virtio_add_queue(&vhk->vdev, MAX_BUF_COUNT, maru_virtio_hwkey_handle); vhk->qdev = dev; diff --git a/tizen/src/hw/maru_virtio_touchscreen.c b/tizen/src/hw/maru_virtio_touchscreen.c index f5b041b5a4..142082e7ab 100644 --- a/tizen/src/hw/maru_virtio_touchscreen.c +++ b/tizen/src/hw/maru_virtio_touchscreen.c @@ -31,6 +31,7 @@ #include "console.h" #include "maru_virtio_touchscreen.h" #include "maru_device_ids.h" +#include "emul_state.h" #include "debug_ch.h" MULTI_DEBUG_CHANNEL(qemu, touchscreen); @@ -106,7 +107,7 @@ void virtio_touchscreen_event(void *opaque, int x, int y, int z, int buttons_sta pthread_mutex_lock(&event_mutex); - entry->index = ++event_queue_cnt; // 1 ~ + entry->index = ++event_queue_cnt; /* 1 ~ */ QTAILQ_INSERT_TAIL(&events_queue, entry, node); @@ -268,10 +269,27 @@ void maru_virtio_touchscreen_notify(void) } } +static void virtio_touchscreen_get_config( + VirtIODevice *vdev, uint8_t *config_data) +{ + int max_trkid = 10; + INFO("virtio_touchscreen_get_config\n"); + + max_trkid = get_emul_max_touch_point(); + memcpy(config_data, &max_trkid, 4); +} + +static void virtio_touchscreen_set_config( + VirtIODevice *vdev, const uint8_t *config_data) +{ + /* do nothing */ +} + static uint32_t virtio_touchscreen_get_features( VirtIODevice *vdev, uint32_t request_features) { - // TODO: + /* do nothing */ + return request_features; } @@ -287,16 +305,18 @@ VirtIODevice *maru_virtio_touchscreen_init(DeviceState *dev) INFO("initialize the touchscreen device\n"); ts = (TouchscreenState *)virtio_common_init(DEVICE_NAME, - VIRTIO_ID_TOUCHSCREEN, 0 /*config_size*/, sizeof(TouchscreenState)); + VIRTIO_ID_TOUCHSCREEN, 4, sizeof(TouchscreenState)); if (ts == NULL) { ERR("failed to initialize the touchscreen device\n"); return NULL; } + ts->vdev.get_config = virtio_touchscreen_get_config; + ts->vdev.set_config = virtio_touchscreen_set_config; ts->vdev.get_features = virtio_touchscreen_get_features; - ts->vq = virtio_add_queue(&ts->vdev, 64, maru_virtio_touchscreen_handle); + ts->vq = virtio_add_queue(&ts->vdev, 64, maru_virtio_touchscreen_handle); ts->qdev = dev; /* reset the counters */ diff --git a/tizen/src/hw/opengl_exec.c b/tizen/src/hw/opengl_exec.c index 0fee10ce71..337fad2aed 100644 --- a/tizen/src/hw/opengl_exec.c +++ b/tizen/src/hw/opengl_exec.c @@ -29,7 +29,8 @@ #include #include #include -#include // for pid_t +#include +#include // for pid_t #include "qemu-common.h" @@ -50,7 +51,7 @@ */ #include "tizen/src/debug_ch.h" MULTI_DEBUG_CHANNEL(qemu, opengl); -#define DEBUGF TRACE +#define DEBUGF TRACE #define GL_GLEXT_PROTOTYPES #define GLX_GLXEXT_PROTOTYPES @@ -63,7 +64,6 @@ MULTI_DEBUG_CHANNEL(qemu, opengl); #include "range_alloc.h" #include "gloffscreen.h" - /** Misc X11/GLX defines - we don't want to include the whole files for these * as we need them on Windows too */ typedef int Bool; @@ -71,7 +71,7 @@ const Bool True = 1; const Bool False = 0; typedef struct __GLXFBConfigRec GLXFBConfig; struct __GLXFBConfigRec { - int formatFlags; + int formatFlags; }; // #defines from glx.h @@ -81,9 +81,9 @@ struct __GLXFBConfigRec { /* We'll say the XVisual Id is actually just an index into here */ const GLXFBConfig FBCONFIGS[] = { - {GLO_FF_ALPHA|GLO_FF_BITS_32}, - {GLO_FF_ALPHA|GLO_FF_BITS_32|GLO_FF_DEPTH_24}, - {GLO_FF_ALPHA|GLO_FF_BITS_32|GLO_FF_DEPTH_24|GLO_FF_STENCIL_8}, + {GLO_FF_ALPHA | GLO_FF_BITS_32}, + {GLO_FF_ALPHA | GLO_FF_BITS_32 | GLO_FF_DEPTH_24}, + {GLO_FF_ALPHA | GLO_FF_BITS_32 | GLO_FF_DEPTH_24 | GLO_FF_STENCIL_8}, /* {GLO_FF_BITS_32}, {GLO_FF_BITS_32|GLO_FF_DEPTH_24}, @@ -104,35 +104,36 @@ const GLXFBConfig FBCONFIGS[] = { #define FAKE_GL_VERSION "1.4" #define FAKE_GL_MAJOR 1 - #define FAKE_GLX_VENDOR "Qemu" #define FAKE_GLX_VERSION_STRING "1.2" #define FAKE_GLX_VERSION_MAJOR 1 #define FAKE_GLX_VERSION_MINOR 2 -void *g_malloc(size_t size); -void *g_realloc(void *ptr, size_t size); -void g_free(void *ptr); - /*#define glGetError() 0*/ +#ifdef WIN32 +# define CCONV _stdcall /* DLL entry points are WINAPI */ +#else +# define CCONV +#endif + #define GET_EXT_PTR(type, funcname, args_decl) \ static int detect_##funcname = 0; \ - static type(*ptr_func_##funcname)args_decl = NULL; \ + static type CCONV (*ptr_func_##funcname)args_decl = NULL; \ if (detect_##funcname == 0) \ { \ detect_##funcname = 1; \ - ptr_func_##funcname = (type(*)args_decl)glo_getprocaddress((const char*)#funcname); \ + ptr_func_##funcname = (type CCONV (*)args_decl)glo_getprocaddress((const char*)#funcname); \ assert (ptr_func_##funcname); \ } #define GET_EXT_PTR_NO_FAIL(type, funcname, args_decl) \ static int detect_##funcname = 0; \ - static type(*ptr_func_##funcname)args_decl = NULL; \ + static type CCONV (*ptr_func_##funcname)args_decl = NULL; \ if (detect_##funcname == 0) \ { \ detect_##funcname = 1; \ - ptr_func_##funcname = (type(*)args_decl)glo_getprocaddress((const char*)#funcname); \ + ptr_func_##funcname = (type CCONV (*)args_decl)glo_getprocaddress((const char*)#funcname); \ } #ifndef WIN32 @@ -141,15 +142,15 @@ void g_free(void *ptr); static void *get_glu_ptr(const char *name) { - static void *handle = (void *) -1; + static void *handle = (void *)-1; - if (handle == (void *) -1) { + if (handle == (void *)-1) { #ifndef WIN32 handle = dlopen("libGLU.so", RTLD_LAZY); if (!handle) DEBUGF("can't load libGLU.so : %s\n", dlerror()); #else - handle = (void *) LoadLibrary("glu32.dll"); + handle = (void *)LoadLibrary("glu32.dll"); if (!handle) DEBUGF("can't load glu32.dll\n"); #endif @@ -166,11 +167,11 @@ static void *get_glu_ptr(const char *name) #define GET_GLU_PTR(type, funcname, args_decl) \ static int detect_##funcname = 0; \ - static type(*ptr_func_##funcname)args_decl = NULL; \ + static type CCONV (*ptr_func_##funcname)args_decl = NULL; \ if (detect_##funcname == 0) \ { \ detect_##funcname = 1; \ - ptr_func_##funcname = (type(*)args_decl)get_glu_ptr(#funcname); \ + ptr_func_##funcname = (type CCONV (*)args_decl)get_glu_ptr(#funcname); \ } int display_function_call = 0; @@ -198,7 +199,7 @@ typedef struct { #define MAX_CLIENT_STATE_STACK_SIZE 16 -typedef void *ClientGLXDrawable; +typedef uint32_t ClientGLXDrawable; typedef struct GLState GLState; @@ -209,19 +210,19 @@ enum { }; enum { - SURFACE_PENDING, /* Created with light-weight context */ - SURFACE_ACTIVE, /* Ready after MakeCurrent */ + SURFACE_PENDING, /* Created with light-weight context */ + SURFACE_ACTIVE, /* Ready after MakeCurrent */ }; typedef struct QGloSurface { GLState *glstate; GloSurface *surface; - ClientGLXDrawable *client_drawable; - int type; /* window, pixmap or pbuffer */ + ClientGLXDrawable client_drawable; + int type; /* window, pixmap or pbuffer */ int ready; - int status; + int status; int ref; - QTAILQ_ENTRY(QGloSurface) next; + QTAILQ_ENTRY(QGloSurface) next; } QGloSurface; #define MAX_PIXMAP_TEXTURE 32 @@ -231,15 +232,20 @@ typedef struct PixmapTexture { ClientGLXDrawable drawable; } PixmapTexture; +typedef struct ClientTabValues { + unsigned int count; + unsigned int *values; +} ClientTabValues; + struct GLState { int ref; int fake_ctxt; int fake_shareList; - GloContext *context; // context (owned by this) - QGloSurface *current_qsurface; // current rendering surface/drawable - QTAILQ_HEAD(, QGloSurface) qsurfaces; // list of surfaces/drawables for - // this context + GloContext *context; // context (owned by this) + QGloSurface *current_qsurface; // current rendering surface/drawable + QTAILQ_HEAD(, QGloSurface) qsurfaces; // list of surfaces/drawables for + // this context void *vertexPointer; void *normalPointer; @@ -282,26 +288,33 @@ struct GLState { int clientStateSp; int activeTextureIndex; - unsigned int ownTabTextures[32768]; - unsigned int *tabTextures; /* The mapping between the texture and pixmap used as texture */ PixmapTexture pixmapTextures[MAX_PIXMAP_TEXTURE]; unsigned int bindTexture2D; + + ClientTabValues ownTabTextures; + ClientTabValues *tabTextures; RangeAllocator ownTextureAllocator; RangeAllocator *textureAllocator; - unsigned int ownTabBuffers[32768]; - unsigned int *tabBuffers; + ClientTabValues ownTabBuffers; + ClientTabValues *tabBuffers; RangeAllocator ownBufferAllocator; RangeAllocator *bufferAllocator; - unsigned int ownTabLists[32768]; - unsigned int *tabLists; + ClientTabValues ownTabLists; + ClientTabValues *tabLists; RangeAllocator ownListAllocator; RangeAllocator *listAllocator; }; +struct GLCallStatInfo { + uint64_t n; // Number of time a function is called + uint64_t max; // Maximum number of ms spent here + uint64_t total; // Total number of ms spent here +}; + typedef struct { ProcessStruct p; @@ -319,33 +332,43 @@ typedef struct { QGloSurface **pending_qsurfaces; int nb_qsurf; + /* Number of FB configs sets allocated on behalf of this process */ int nfbconfig; + + /* Array of FB configs sets */ const GLXFBConfig *fbconfigs[MAX_FBCONFIG]; + + /* Number of FB configs per set */ int fbconfigs_max[MAX_FBCONFIG]; + + /* Total number of FB configs allocated on behalf of this process */ int nfbconfig_total; int primitive; int bufsize; int bufstart; arg_t *cmdbuf; + + struct GLCallStatInfo stats[GL_N_CALLS]; } ProcessState; static ProcessState processes[MAX_HANDLED_PROCESS]; -static char *strip_extensions(const char *avail, const char *ext[]) { +static char *strip_extensions(const char *avail, const char *ext[]) +{ char *pos, *supported, *srcp; supported = (char *)g_malloc(strlen(avail) + 2); pos = supported; - while(*ext) { - srcp = (char*)avail; - while((srcp = strstr(srcp, *ext))) { + while (*ext) { + srcp = (char *)avail; + while ((srcp = strstr(srcp, *ext))) { int len = strlen(*ext); - if(*(srcp+len) == ' ' || *(srcp+len) == '\0') { + if (*(srcp + len) == ' ' || *(srcp + len) == '\0') { strcpy(pos, *ext); pos += len; - if(*(srcp+len) == ' ') { + if (*(srcp + len) == ' ') { *pos = ' '; pos++; } @@ -358,20 +381,27 @@ static char *strip_extensions(const char *avail, const char *ext[]) { *pos = ' '; *pos = '\0'; - return supported; + return supported; } +extern void vmgl_context_switch(ProcessStruct * p, int switch_gl_context); +extern ProcessStruct *vmgl_get_process(pid_t pid); +extern void gl_disconnect(ProcessState * process); +extern int do_function_call(ProcessState * process, int func_number, + unsigned long *args, char *ret_string); + static const char *glx_ext_supported[] = { "GLX_ARB_multisample", 0 }; -static char *supported_glx_extensions() { +static char *supported_glx_extensions(void) +{ static char *supported; - if(!supported) - supported = strip_extensions(glo_glXQueryExtensionsString(), - glx_ext_supported); + if (!supported) + supported = strip_extensions(glo_glXQueryExtensionsString(), + glx_ext_supported); return supported; } @@ -436,7 +466,7 @@ static const char *gl_ext_supported[] = { "GL_ARB_fragment_shader", "GL_ARB_framebuffer_object", "GL_ARB_half_float_pixel", - "GL_ARB_map_buffer_range", + "GL_ARB_map_buffer_range", "GL_ARB_occlusion_query", "GL_ARB_pixel_buffer_object", "GL_ARB_point_sprite", @@ -445,27 +475,26 @@ static const char *gl_ext_supported[] = { "GL_ARB_shader_objects", "GL_ARB_shading_language_100", "GL_ARB_shading_language_120", - "GL_ARB_sync", + "GL_ARB_sync", "GL_ARB_texture_non_power_of_two", "GL_ARB_texture_rectangle", - "GL_ARB_vertex_array_bgra", + "GL_ARB_vertex_array_bgra", "GL_ARB_vertex_array_object", "GL_ARB_vertex_buffer_object", "GL_ARB_vertex_program", - "GL_ARB_vertex_shader," - "GL_EXT_abgr", + "GL_ARB_vertex_shader," "GL_EXT_abgr", "GL_EXT_blend_equation_separate", "GL_EXT_cull_vertex", "GL_EXT_framebuffer_blit", "GL_EXT_framebuffer_object", - "GL_EXT_gpu_program_parameters", - "GL_EXT_packed_depth_stencil", + "GL_EXT_gpu_program_parameters", + "GL_EXT_packed_depth_stencil", "GL_EXT_pixel_buffer_object", "GL_EXT_provoking_vertex", "GL_EXT_shadow_funcs", "GL_EXT_stencil_two_side", - "GL_EXT_texture_cube_map", - "GL_EXT_texture_env_dot3", + "GL_EXT_texture_cube_map", + "GL_EXT_texture_env_dot3", "GL_EXT_texture_filter_anisotropic", "GL_EXT_texture_rectangle", "GL_EXT_texture_sRGB", @@ -474,7 +503,7 @@ static const char *gl_ext_supported[] = { "GL_EXT_vertex_array_bgra", "GL_3DFX_texture_compression_FXT1", "GL_APPLE_client_storage", - "GL_APPLE_vertex_array_object", + "GL_APPLE_vertex_array_object", "GL_ATI_blend_equation_separate", "GL_ATI_envmap_bumpmap", "GL_ATI_texture_env_combine3", @@ -482,7 +511,7 @@ static const char *gl_ext_supported[] = { "GL_IBM_multimode_draw_arrays", "GL_IBM_rasterpos_clip", "GL_IBM_texture_mirrored_repeat", - "GL_INGR_blend_func_separate", + "GL_INGR_blend_func_separate", "GL_MESA_pack_invert", "GL_MESA_texture_signed_rgba", "GL_MESA_ycbcr_texture", @@ -500,20 +529,64 @@ static const char *gl_ext_supported[] = { 0 }; -static char *compute_gl_extensions() { +static char *compute_gl_extensions(void) +{ static char *supported; - if(!supported) + if (!supported) supported = strip_extensions((const char *)glGetString(GL_EXTENSIONS), gl_ext_supported); return supported; } -static inline QGloSurface *get_qsurface_from_client_drawable(GLState *state, ClientGLXDrawable client_drawable) { +static int alloc_space(ClientTabValues *tabValues, unsigned int client_value, int zero) +{ + ClientTabValues tv; + + tv.values = tabValues->values; + tv.count = tabValues->count; + + while (client_value >= tv.count) { + tv.count = (tv.count == 0) ? 4 : tv.count * 2; + } + + if (tv.count != tabValues->count) { + DEBUGF("Reallocate array of %d uint\n", tv.count); + tv.values = g_realloc(tv.values, tv.count * sizeof(unsigned int)); + if (zero) + memset(tv.values + tabValues->count, 0, + (tv.count - tabValues->count) * sizeof(unsigned int)); + } + + if (!tv.values) { + DEBUGF("Failed to allocate array of %d uint\n", tv.count); + return 0; + } + + *tabValues = tv; + + return 1; +} + +static void free_space(ClientTabValues *tabValues, unsigned int client_value) +{ + if (client_value < tabValues->count) { + tabValues->values[client_value] = 0; + /* FIXME we should compact the tabValues data here */ + } else { + DEBUGF("Tried to free client_value %d of %d\n", client_value, tabValues->count); + } +} + +static inline QGloSurface *get_qsurface_from_client_drawable(GLState * state, + ClientGLXDrawable + client_drawable) +{ QGloSurface *qsurface; - if(state->current_qsurface->client_drawable == client_drawable) + if (state->current_qsurface + && state->current_qsurface->client_drawable == client_drawable) return state->current_qsurface; QTAILQ_FOREACH(qsurface, &state->qsurfaces, next) { @@ -525,20 +598,73 @@ static inline QGloSurface *get_qsurface_from_client_drawable(GLState *state, Cli } // This must always be called only on surfaces belonging to the current context -static inline void render_surface(QGloSurface *qsurface, int bpp, int stride, char *buffer) +static inline void render_surface(QGloSurface * qsurface, int bpp, int stride, + char *buffer) { int w, h; - if(!qsurface->ready) - return; + if (!qsurface->ready) + return; glo_surface_get_size(qsurface->surface, &w, &h); glo_surface_getcontents(qsurface->surface, stride, bpp, buffer); } +static void qsurface_pixmap_ref(QGloSurface * qsurface) +{ + if (!qsurface) { + DEBUGF("%s %p\n", __FUNCTION__, qsurface); + return; + } + + if (qsurface->type != SURFACE_PIXMAP) { + DEBUGF("%s %p is not a pixmap\n", __FUNCTION__, qsurface); + return; + } + + qsurface->ref++; + DEBUGF("%s %p references increased to %d\n", __FUNCTION__, qsurface, + qsurface->ref); +} + +static void qsurface_pixmap_unref(QGloSurface * qsurface) +{ + if (!qsurface) { + DEBUGF("%s %p\n", __FUNCTION__, qsurface); + return; + } + + if (qsurface->type != SURFACE_PIXMAP) { + DEBUGF("%s %p is not a pixmap\n", __FUNCTION__, qsurface); + return; + } + + qsurface->ref--; + DEBUGF("%s %p references decreased to %d\n", __FUNCTION__, qsurface, + qsurface->ref); + + if (qsurface->ref == 0) { + glo_surface_destroy(qsurface->surface); + g_free(qsurface); + DEBUGF("%s freed: %p\n", __FUNCTION__, qsurface); + } +} + +static void state_set_current_surface(GLState * state, QGloSurface * qsurface) +{ + if (state->current_qsurface != NULL) + qsurface_pixmap_unref(state->current_qsurface); + + if (qsurface != NULL) + qsurface_pixmap_ref(qsurface); + + state->current_qsurface = qsurface; +} + // This must always be called only on surfaces belonging to the current context -static inline void resize_surface(ProcessState *process, QGloSurface *qsurface, - int w, int h) { +static inline void resize_surface(ProcessState * process, + QGloSurface * qsurface, int w, int h) +{ GLState *glstate = qsurface->glstate; GloSurface *old_surface = qsurface->surface; GloSurface *surface; @@ -551,7 +677,7 @@ static inline void resize_surface(ProcessState *process, QGloSurface *qsurface, qsurface->surface = surface; // Client doesnt know surface is new - need to MakeCurrent - if(process->current_state == qsurface->glstate) { + if (process->current_state == qsurface->glstate) { glo_surface_makecurrent(qsurface->surface); // set the viewport while the window size is changed. It is needed // especially for the case that glViewport is not explicitly called @@ -559,9 +685,8 @@ static inline void resize_surface(ProcessState *process, QGloSurface *qsurface, // in the first MakeCurrent when the window size is not known. // It will not impact normal GL programs with glViewport set as // programmers want. - glViewport (0, 0, w, h); - } - else { + glViewport(0, 0, w, h); + } else { DEBUGF("Error: Surface is not current! %p %p\n", process->current_state, process->current_state->current_qsurface); @@ -569,82 +694,82 @@ static inline void resize_surface(ProcessState *process, QGloSurface *qsurface, } glstate->current_qsurface->ready = 1; - DEBUGF( "resize_done\n"); + DEBUGF("resize_done\n"); } - -void init_process_tab() +static void init_process_tab(void) { memset(processes, 0, sizeof(processes)); } -#define ARG_TO_CHAR(x) (char)(x) -#define ARG_TO_UNSIGNED_CHAR(x) (unsigned char)(x) -#define ARG_TO_SHORT(x) (short)(x) -#define ARG_TO_UNSIGNED_SHORT(x) (unsigned short)(x) -#define ARG_TO_INT(x) (int)(x) -#define ARG_TO_UNSIGNED_INT(x) (unsigned int)(x) +#define ARG_TO_CHAR(x) (char)(long)(x) +#define ARG_TO_UNSIGNED_CHAR(x) (unsigned char)(long)(x) +#define ARG_TO_SHORT(x) (short)(long)(x) +#define ARG_TO_UNSIGNED_SHORT(x) (unsigned short)(long)(x) +#define ARG_TO_INT(x) (int)(long)(x) +#define ARG_TO_UNSIGNED_INT(x) (unsigned int)(long)(x) #define ARG_TO_FLOAT(x) (*(float*)&(x)) #define ARG_TO_DOUBLE(x) (*(double*)(x)) #include "server_stub.c" -//typedef void *ClientGLXDrawable; static inline ClientGLXDrawable to_drawable(arg_t arg) { #ifdef TARGET_X86_64 - if (arg > (unsigned long) -1) { - DEBUGF( "GLXDrawable too big for this implementation\n"); + if (arg > (unsigned long)-1) { + DEBUGF("GLXDrawable too big for this implementation\n"); exit(-1); } #endif - return (void *) (unsigned long) arg; + return (ClientGLXDrawable) arg; } /* ---- */ /* Bind a qsurface to a context (GLState) */ -static void bind_qsurface(GLState *state, - QGloSurface *qsurface) +static void bind_qsurface(GLState * state, QGloSurface * qsurface) { - DEBUGF("%s qsurface %p qsurface->glstate %p new state %p\n", __FUNCTION__, qsurface, qsurface->glstate, state); + DEBUGF("%s qsurface %p qsurface->glstate %p new state %p\n", __FUNCTION__, + qsurface, qsurface->glstate, state); qsurface->glstate = state; - if ( qsurface->type == SURFACE_WINDOW ) - QTAILQ_INSERT_HEAD(&state->qsurfaces, qsurface, next); + if (qsurface->type == SURFACE_WINDOW) + QTAILQ_INSERT_HEAD(&state->qsurfaces, qsurface, next); - state->current_qsurface = qsurface; + state_set_current_surface(state, qsurface); } /* Unbind a qsurface from a context (GLState) */ -static void unbind_qsurface(GLState *state, - QGloSurface *qsurface) +static void unbind_qsurface(GLState * state, QGloSurface * qsurface) { if (!state || !qsurface) { - DEBUGF("%s invalid parameter, state %p, qsurface %p\n", __FUNCTION__, state, qsurface); + DEBUGF("%s invalid parameter, state %p, qsurface %p\n", __FUNCTION__, + state, qsurface); return; } - DEBUGF("%s qsurface %p qsurface->glstate %p old state %p\n", __FUNCTION__, qsurface, qsurface->glstate, state); + DEBUGF("%s qsurface %p qsurface->glstate %p old state %p\n", __FUNCTION__, + qsurface, qsurface->glstate, state); qsurface->glstate = NULL; - if ( qsurface->type == SURFACE_WINDOW ) - QTAILQ_REMOVE(&state->qsurfaces, qsurface, next); + if (qsurface->type == SURFACE_WINDOW) + QTAILQ_REMOVE(&state->qsurfaces, qsurface, next); - if ( state->current_qsurface == qsurface ) - state->current_qsurface = NULL; + if (state->current_qsurface == qsurface) + state_set_current_surface(state, NULL); } /* Find the qsurface with required drawable in all pixmap/pbuffer surfaces */ -QGloSurface* find_qsurface_from_client_drawable(ProcessState *process, ClientGLXDrawable client_drawable) +static QGloSurface *find_qsurface_from_client_drawable(ProcessState * process, + ClientGLXDrawable + client_drawable) { int i; QGloSurface *qsurface; - for ( i = 0; i < process->nb_qsurf; i++ ) - { + for (i = 0; i < process->nb_qsurf; i++) { qsurface = process->pending_qsurfaces[i]; - if ( qsurface && qsurface->client_drawable == client_drawable ) + if (qsurface && qsurface->client_drawable == client_drawable) return qsurface; } @@ -652,35 +777,34 @@ QGloSurface* find_qsurface_from_client_drawable(ProcessState *process, ClientGLX } /* Make the appropriate qsurface current for a given client_drawable */ -static int set_current_qsurface(GLState *state, +static int set_current_qsurface(GLState * state, ClientGLXDrawable client_drawable) { QGloSurface *qsurface; - if(state->current_qsurface && state->current_qsurface->client_drawable == client_drawable) + if (state->current_qsurface + && state->current_qsurface->client_drawable == client_drawable) return 1; QTAILQ_FOREACH(qsurface, &state->qsurfaces, next) { - if(qsurface->client_drawable == client_drawable) { - state->current_qsurface = qsurface; - qsurface->glstate = state; + if (qsurface->client_drawable == client_drawable) { + state_set_current_surface(state, qsurface); + qsurface->glstate = state; return 1; } } - state->current_qsurface = NULL; + state_set_current_surface(state, NULL); return 0; } /* */ -static int keep_drawable(ProcessState *process, ClientGLXDrawable drawable) +static int keep_drawable(ProcessState * process, ClientGLXDrawable drawable) { int i; - for ( i = 0; i < MAX_PENDING_DRAWABLE; i++) - { - if ( process->pending_drawables[i] == 0 ) - { + for (i = 0; i < MAX_PENDING_DRAWABLE; i++) { + if (process->pending_drawables[i] == 0) { process->pending_drawables[i] = drawable; return 1; } @@ -688,13 +812,11 @@ static int keep_drawable(ProcessState *process, ClientGLXDrawable drawable) return 0; } -static int link_drawable(ProcessState *process, ClientGLXDrawable drawable) +static int link_drawable(ProcessState * process, ClientGLXDrawable drawable) { int i; - for ( i = 0; i < MAX_PENDING_DRAWABLE; i++ ) - { - if ( process->pending_drawables[i] == drawable ) - { + for (i = 0; i < MAX_PENDING_DRAWABLE; i++) { + if (process->pending_drawables[i] == drawable) { process->pending_drawables[i] = 0; return 1; } @@ -707,26 +829,25 @@ static int link_drawable(ProcessState *process, ClientGLXDrawable drawable) * 1. Create one light-weight context just for surface creation. * 2. Store this qsurface, and link it with right context when MakeCurrent */ -static void keep_qsurface(ProcessState *process, QGloSurface *qsurface) +static void keep_qsurface(ProcessState * process, QGloSurface * qsurface) { process->pending_qsurfaces = g_realloc(process->pending_qsurfaces, - (process->nb_qsurf + 1) * sizeof(QGloSurface*)); + (process->nb_qsurf + 1) * sizeof(QGloSurface *)); process->pending_qsurfaces[process->nb_qsurf] = qsurface; process->nb_qsurf++; } -static int link_qsurface(ProcessState *process, GLState *glstate, ClientGLXDrawable client_drawable) +static int link_qsurface(ProcessState * process, GLState * glstate, + ClientGLXDrawable client_drawable) { int i; QGloSurface *qsurface; - for ( i = 0; i < process->nb_qsurf; i++ ) - { + for (i = 0; i < process->nb_qsurf; i++) { qsurface = process->pending_qsurfaces[i]; - if ( qsurface && qsurface->client_drawable == client_drawable ) - { + if (qsurface && qsurface->client_drawable == client_drawable) { /* XXX:Current limitation is that each surface is binded to one * context, and not accessible from another context. It's hard for * glEGLImageTargetTexture2DOES implementation, in which we need @@ -736,22 +857,25 @@ static int link_qsurface(ProcessState *process, GLState *glstate, ClientGLXDrawa * */ #if 0 memmove(&process->pending_qsurfaces[i], - &process->pending_qsurfaces[i+1], - (process->nb_qsurf - i - 1) * sizeof(QGloSurface*)); + &process->pending_qsurfaces[i + 1], + (process->nb_qsurf - i - 1) * sizeof(QGloSurface *)); #endif - qsurface->ref = 1; - if(qsurface->status == SURFACE_PENDING) - { - glo_surface_update_context(qsurface->surface, glstate->context, 1); - qsurface->status = SURFACE_ACTIVE; - } - else - { - unbind_qsurface(qsurface->glstate, qsurface); - glo_surface_update_context(qsurface->surface, glstate->context, 0); - - } + if (qsurface->type != SURFACE_PIXMAP) { + DEBUGF + ("%s Forcing non pixmap qsurface->ref to 1 (type %d, ref %d)\n", + __FUNCTION__, qsurface->type, qsurface->ref); + qsurface->ref = 1; + } + if (qsurface->status == SURFACE_PENDING) { + glo_surface_update_context(qsurface->surface, glstate->context, + 1); + qsurface->status = SURFACE_ACTIVE; + } else { + unbind_qsurface(qsurface->glstate, qsurface); + glo_surface_update_context(qsurface->surface, glstate->context, + 0); + } bind_qsurface(glstate, qsurface); return 1; @@ -765,15 +889,12 @@ static int link_qsurface(ProcessState *process, GLState *glstate, ClientGLXDrawa * and glXBindTexImage, so need keep the mapping between them to add proper * action when bind the texture again */ -static void del_pixmap_texture_mapping(GLState *state, - unsigned int texture) +static void del_pixmap_texture_mapping(GLState * state, unsigned int texture) { int i; - for ( i = 0; i < MAX_PIXMAP_TEXTURE; i++ ) - { - if ( state->pixmapTextures[i].used && - state->pixmapTextures[i].texture == texture ) - { + for (i = 0; i < MAX_PIXMAP_TEXTURE; i++) { + if (state->pixmapTextures[i].used && + state->pixmapTextures[i].texture == texture) { state->pixmapTextures[i].used = 0; state->pixmapTextures[i].texture = 0; state->pixmapTextures[i].drawable = 0; @@ -782,15 +903,13 @@ static void del_pixmap_texture_mapping(GLState *state, } } -static void remove_pixmap_texture_mapping(GLState *state, - ClientGLXDrawable drawable) +static void remove_pixmap_texture_mapping(GLState * state, + ClientGLXDrawable drawable) { int i; - for ( i = 0; i < MAX_PIXMAP_TEXTURE; i++ ) - { - if ( state->pixmapTextures[i].used && - state->pixmapTextures[i].drawable == drawable ) - { + for (i = 0; i < MAX_PIXMAP_TEXTURE; i++) { + if (state->pixmapTextures[i].used && + state->pixmapTextures[i].drawable == drawable) { state->pixmapTextures[i].used = 0; state->pixmapTextures[i].texture = 0; state->pixmapTextures[i].drawable = 0; @@ -799,15 +918,14 @@ static void remove_pixmap_texture_mapping(GLState *state, } } -static int add_pixmap_texture_mapping(GLState *state, - unsigned int texture, ClientGLXDrawable drawable) +static int add_pixmap_texture_mapping(GLState * state, + unsigned int texture, + ClientGLXDrawable drawable) { int i; - for ( i = 0; i < MAX_PIXMAP_TEXTURE; i++ ) - { - if ( state->pixmapTextures[i].texture == texture || - !state->pixmapTextures[i].used ) - { + for (i = 0; i < MAX_PIXMAP_TEXTURE; i++) { + if (state->pixmapTextures[i].texture == texture || + !state->pixmapTextures[i].used) { state->pixmapTextures[i].used = 1; state->pixmapTextures[i].texture = texture; state->pixmapTextures[i].drawable = drawable; @@ -818,69 +936,73 @@ static int add_pixmap_texture_mapping(GLState *state, return 0; } -static ClientGLXDrawable find_pixmap_texture(GLState *state, - unsigned int texture) +static ClientGLXDrawable find_pixmap_texture(GLState * state, + unsigned int texture) { int i; - for ( i = 0; i < MAX_PIXMAP_TEXTURE; i++ ) - { - if ( state->pixmapTextures[i].used && - state->pixmapTextures[i].texture == texture ) + for (i = 0; i < MAX_PIXMAP_TEXTURE; i++) { + if (state->pixmapTextures[i].used && + state->pixmapTextures[i].texture == texture) return state->pixmapTextures[i].drawable; } return 0; } -static int get_server_texture(ProcessState *process, +static int get_server_texture(ProcessState * process, unsigned int client_texture) { unsigned int server_texture = 0; - if (client_texture < 32768) { - server_texture = process->current_state->tabTextures[client_texture]; + if (client_texture < process->current_state->tabTextures->count) { + server_texture = process->current_state->tabTextures->values[client_texture]; } else { - DEBUGF( "invalid texture name %d\n", client_texture); + DEBUGF("invalid texture name %d\n", client_texture); } return server_texture; } -static int get_server_buffer(ProcessState *process, - unsigned int client_buffer) +static int get_server_buffer(ProcessState * process, unsigned int client_buffer) { unsigned int server_buffer = 0; - if (client_buffer < 32768) { - server_buffer = process->current_state->tabBuffers[client_buffer]; + if (client_buffer < process->current_state->tabBuffers->count) { + server_buffer = process->current_state->tabBuffers->values[client_buffer]; } else { - DEBUGF( "invalid buffer name %d\n", client_buffer); + DEBUGF("invalid buffer name %d\n", client_buffer); } return server_buffer; } - -static int get_server_list(ProcessState *process, unsigned int client_list) +static int get_server_list(ProcessState * process, unsigned int client_list) { unsigned int server_list = 0; - if (client_list < 32768) { - server_list = process->current_state->tabLists[client_list]; + if (client_list < process->current_state->tabLists->count) { + server_list = process->current_state->tabLists->values[client_list]; } else { - DEBUGF( "invalid list name %d\n", client_list); + DEBUGF("invalid list name %d\n", client_list); } return server_list; } -const GLXFBConfig *get_fbconfig(ProcessState *process, int client_fbconfig) +static const GLXFBConfig *get_fbconfig(ProcessState * process, + int client_fbconfig) { int i; + + /* The client_fbconfig returned to upper layers is 1 + the index of the + * fb config in the set that contains it, + the number of fb configs + * store in previously allocated sets. */ int nbtotal = 0; + /* For each set */ for (i = 0; i < process->nfbconfig; i++) { - assert(client_fbconfig >= 1 + nbtotal); + /* If the fb config is stored within this set, return it */ if (client_fbconfig <= nbtotal + process->fbconfigs_max[i]) { return &process->fbconfigs[i][client_fbconfig - 1 - nbtotal]; } + /* Otherwise proceed to next set */ nbtotal += process->fbconfigs_max[i]; } return 0; @@ -896,75 +1018,87 @@ static int glXChooseVisualFunc(const int *attrib_list) int bestConfig = 0; int bestScore = -1; - for (i=0;i 0) - DEBUGF( "Got format flags %d but we couldn't find an exactly matching config, chose %d\n", formatFlags, bestConfig); + DEBUGF + ("Got format flags %d but we couldn't find an exactly matching config, chose %d\n", + formatFlags, bestConfig); return bestConfig; } -static int glXGetConfigFunc(int visualid, int attrib, int *value) { - const GLXFBConfig *config = &FBCONFIGS[0]; // default +static int glXGetConfigFunc(int visualid, int attrib, int *value) +{ + const GLXFBConfig *config = &FBCONFIGS[0]; // default int v; - if (visualid>=0 && visualid= 0 && visualid < DIM(FBCONFIGS)) config = &FBCONFIGS[visualid]; else - DEBUGF( "Unknown visual ID %d\n", visualid); + DEBUGF("Unknown visual ID %d\n", visualid); v = glo_get_glx_from_flags(config->formatFlags, attrib); if (value) - *value = v; + *value = v; return 0; } -static const GLXFBConfig * glXGetFBConfigsFunc(int screen, int *nelements) { +static const GLXFBConfig *glXGetFBConfigsFunc(int screen, int *nelements) +{ *nelements = DIM(FBCONFIGS); return &FBCONFIGS[0]; } -static int glXGetFBConfigAttribFunc(const GLXFBConfig *fbconfig, int attrib, int *value) { +static int glXGetFBConfigAttribFunc(const GLXFBConfig * fbconfig, int attrib, + int *value) +{ // TODO other enums - see http://www.opengl.org/sdk/docs/man/xhtml/glXGetFBConfigAttrib.xml int v = glo_get_glx_from_flags(fbconfig->formatFlags, attrib); - if (value) *value = v; + if (value) + *value = v; return 0; } -static const GLXFBConfig *glXChooseFBConfigFunc(int screen, const int *attrib_list, int *nelements) { +static const GLXFBConfig *glXChooseFBConfigFunc(int screen, + const int *attrib_list, + int *nelements) +{ if (attrib_list != NULL) { int formatFlags = glo_flags_get_from_glx(attrib_list, False); int i; int bestConfig = 0; int bestScore = -1; - for (i=0;i 0) { - DEBUGF( "Got format flags %d but we couldn't find an exactly matching config, chose %d\n", formatFlags, bestConfig); + DEBUGF + ("Got format flags %d but we couldn't find an exactly matching config, chose %d\n", + formatFlags, bestConfig); } if (nelements) - *nelements=1; + *nelements = 1; return &FBCONFIGS[bestConfig]; } if (nelements) - *nelements=0; + *nelements = 0; return 0; } @@ -978,7 +1112,7 @@ static void do_glClientActiveTextureARB(int texture) } } -static void destroy_gl_state(GLState *state) +static void destroy_gl_state(GLState * state) { int i; @@ -991,9 +1125,9 @@ static void destroy_gl_state(GLState *state) QTAILQ_REMOVE(&state->qsurfaces, qsurface, next); g_free(qsurface); } - + if (state->context) - glo_context_destroy(state->context); + glo_context_destroy(state->context); if (state->vertexPointer) g_free(state->vertexPointer); @@ -1031,22 +1165,29 @@ static void destroy_gl_state(GLState *state) g_free(state->interleavedArrays); if (state->elementPointerATI) g_free(state->elementPointerATI); + + if (state->ownTabTextures.values) + g_free(state->ownTabTextures.values); + if (state->ownTabBuffers.values) + g_free(state->ownTabBuffers.values); + if (state->ownTabLists.values) + g_free(state->ownTabLists.values); } -static void init_gl_state(GLState *state) +static void init_gl_state(GLState * state) { state->textureAllocator = &state->ownTextureAllocator; - state->tabTextures = state->ownTabTextures; + state->tabTextures = &state->ownTabTextures; state->bufferAllocator = &state->ownBufferAllocator; - state->tabBuffers = state->ownTabBuffers; + state->tabBuffers = &state->ownTabBuffers; state->listAllocator = &state->ownListAllocator; - state->tabLists = state->ownTabLists; + state->tabLists = &state->ownTabLists; } /* * Translate the nth element of list from type to GLuint. */ -static GLuint translate_id(GLsizei n, GLenum type, const GLvoid *list) +static GLuint translate_id(GLsizei n, GLenum type, const GLvoid * list) { GLbyte *bptr; GLubyte *ubptr; @@ -1059,55 +1200,69 @@ static GLuint translate_id(GLsizei n, GLenum type, const GLvoid *list) switch (type) { case GL_BYTE: bptr = (GLbyte *) list; - return (GLuint) *(bptr + n); + return (GLuint) * (bptr + n); case GL_UNSIGNED_BYTE: ubptr = (GLubyte *) list; - return (GLuint) *(ubptr + n); + return (GLuint) * (ubptr + n); case GL_SHORT: sptr = (GLshort *) list; - return (GLuint) *(sptr + n); + return (GLuint) * (sptr + n); case GL_UNSIGNED_SHORT: usptr = (GLushort *) list; - return (GLuint) *(usptr + n); + return (GLuint) * (usptr + n); case GL_INT: iptr = (GLint *) list; - return (GLuint) *(iptr + n); + return (GLuint) * (iptr + n); case GL_UNSIGNED_INT: uiptr = (GLuint *) list; - return (GLuint) *(uiptr + n); + return (GLuint) * (uiptr + n); case GL_FLOAT: fptr = (GLfloat *) list; - return (GLuint) *(fptr + n); + return (GLuint) * (fptr + n); case GL_2_BYTES: ubptr = ((GLubyte *) list) + 2 * n; - return (GLuint) (*ubptr << 8) + (GLuint) *(ubptr + 1); + return (GLuint) (*ubptr << 8) + (GLuint) * (ubptr + 1); case GL_3_BYTES: ubptr = ((GLubyte *) list) + 3 * n; return (GLuint) (*ubptr << 16) + (GLuint) (*(ubptr + 1) << 8) + - (GLuint) *(ubptr + 2); + (GLuint) * (ubptr + 2); case GL_4_BYTES: ubptr = ((GLubyte *) list) + 4 * n; return (GLuint) (*ubptr << 24) + (GLuint) (*(ubptr + 1) << 16) + - (GLuint) (*(ubptr + 2) << 8) + (GLuint) *(ubptr + 3); + (GLuint) (*(ubptr + 2) << 8) + (GLuint) * (ubptr + 3); default: return 0; } } -GLState *_create_context(ProcessState *process, int fake_ctxt, int fake_shareList) +static GLState *_create_context(ProcessState * process, int fake_ctxt) { - // FIXMEIM - realloc? really? - process->glstates = g_realloc(process->glstates, - (process->nb_states + 1) * sizeof(GLState *)); + GLState *state = g_try_malloc0(sizeof(GLState)); + + if (state) { + state->ref = 1; + state->fake_ctxt = fake_ctxt; + init_gl_state(state); + + // FIXMEIM - realloc? really? + process->glstates = g_realloc(process->glstates, + (process->nb_states + + 1) * sizeof(GLState *)); + + process->glstates[process->nb_states] = state; - process->glstates[process->nb_states] = g_malloc(sizeof(GLState)); - memset(process->glstates[process->nb_states], 0, sizeof(GLState)); + process->nb_states++; + } - process->glstates[process->nb_states]->ref = 1; - process->glstates[process->nb_states]->fake_ctxt = fake_ctxt; - process->glstates[process->nb_states]->fake_shareList = fake_shareList; + DEBUGF("state %p fake_ctxt %08x process->nb_states %d\n", state, fake_ctxt, + process->nb_states); + return state; +} - init_gl_state(process->glstates[process->nb_states]); +static void set_context_sharelist(ProcessState * process, GLState * state, + int fake_shareList) +{ + state->fake_shareList = fake_shareList; if (fake_shareList) { int i; @@ -1115,39 +1270,31 @@ GLState *_create_context(ProcessState *process, int fake_ctxt, int fake_shareLis for (i = 0; i < process->nb_states; i++) { if (process->glstates[i]->fake_ctxt == fake_shareList) { process->glstates[i]->ref++; - process->glstates[process->nb_states]->textureAllocator = + state->textureAllocator = process->glstates[i]->textureAllocator; - process->glstates[process->nb_states]->tabTextures = - process->glstates[i]->tabTextures; - process->glstates[process->nb_states]->bufferAllocator = - process->glstates[i]->bufferAllocator; - process->glstates[process->nb_states]->tabBuffers = - process->glstates[i]->tabBuffers; - process->glstates[process->nb_states]->listAllocator = - process->glstates[i]->listAllocator; - process->glstates[process->nb_states]->tabLists = - process->glstates[i]->tabLists; + state->tabTextures = process->glstates[i]->tabTextures; + state->bufferAllocator = process->glstates[i]->bufferAllocator; + state->tabBuffers = process->glstates[i]->tabBuffers; + state->listAllocator = process->glstates[i]->listAllocator; + state->tabLists = process->glstates[i]->tabLists; break; } } } - process->nb_states++; - - return process->glstates[process->nb_states-1]; } -GLState *get_glstate_for_fake_ctxt(ProcessState *process, int fake_ctxt) +static GLState *get_glstate_for_fake_ctxt(ProcessState * process, int fake_ctxt) { int i; for (i = 0; i < process->nb_states; i++) { if (process->glstates[i]->fake_ctxt == fake_ctxt) return process->glstates[i]; - } + } return 0; } -void gl_disconnect(ProcessState *process) +void gl_disconnect(ProcessState * process) { int i; for (i = 0; i < process->nb_states; i++) { @@ -1160,12 +1307,12 @@ void gl_disconnect(ProcessState *process) if (process->cmdbuf) g_free(process->cmdbuf); - for (i = 0; &processes[i] != process; i ++) { - ; // do nothing - } + for (i = 0; &processes[i] != process; i++) { + ; // do nothing + } - memmove(&processes[i], &processes[i + 1], - (MAX_HANDLED_PROCESS - 1 - i) * sizeof(ProcessState)); + memmove(&processes[i], &processes[i + 1], + (MAX_HANDLED_PROCESS - 1 - i) * sizeof(ProcessState)); } static const int beginend_allowed[GL_N_CALLS] = { @@ -1180,7 +1327,7 @@ ProcessStruct *vmgl_get_process(pid_t pid) static int first; int i; - if(!first) { + if (!first) { first = 1; init_process_tab(); } @@ -1190,7 +1337,7 @@ ProcessStruct *vmgl_get_process(pid_t pid) * process->current_state contains info on which of the guests contexts is * current. */ - for (i = 0; i < MAX_HANDLED_PROCESS; i ++) { + for (i = 0; i < MAX_HANDLED_PROCESS; i++) { if (processes[i].p.process_id == pid) { process = &processes[i]; break; @@ -1202,37 +1349,39 @@ ProcessStruct *vmgl_get_process(pid_t pid) process->current_state = &process->default_state; break; } - } + } if (process == NULL) { - DEBUGF( "Too many processes !\n"); + DEBUGF("Too many processes !\n"); exit(-1); } - return (ProcessStruct *)process; // Cast is ok due to struct defn. + return (ProcessStruct *) process; // Cast is ok due to struct defn. } -void vmgl_context_switch(ProcessStruct *p, int switch_gl_context) +void vmgl_context_switch(ProcessStruct * p, int switch_gl_context) { - ProcessState *process = (ProcessState *)p; - if(switch_gl_context) { - if(process->current_state->current_qsurface) - glo_surface_makecurrent(process->current_state->current_qsurface->surface); + ProcessState *process = (ProcessState *) p; + if (switch_gl_context) { + if (process->current_state->current_qsurface) + glo_surface_makecurrent(process->current_state->current_qsurface-> + surface); else glo_surface_makecurrent(0); // should never happen } } -static const char *opengl_strtok(const char *s, int *n, char **saveptr, char *prevbuf) +static char *opengl_strtok(const char *s, int *n, char const **saveptr, + char *prevbuf) { - char *start; - char *ret; - char *p; - int retlen; + const char *start; + char *ret; + char *p; + int retlen; static const char *delim = " \t\n\r/"; - if (prevbuf) - free(prevbuf); + if (prevbuf) + free(prevbuf); if (s) { *saveptr = s; @@ -1253,162 +1402,168 @@ static const char *opengl_strtok(const char *s, int *n, char **saveptr, char *pr s++, (*n)--; } while (*n > 2 && (s[1] != '*' || s[2] != '/')); s++, (*n)--; - s++, (*n)--; - if (*n == 0) { - break; - } - } else { - break; + s++, (*n)--; + if (*n == 0) { + break; + } + } else { + break; } } } - start = s; + start = s; for (; *n && *s && !strchr(delim, *s); s++, (*n)--) { - ; // do nothing - } + ; // do nothing + } - if (*n > 0) - s++, (*n)--; + if (*n > 0) + s++, (*n)--; - *saveptr = s; + *saveptr = s; - retlen = s - start; - ret = malloc(retlen + 1); - p = ret; + retlen = s - start; + ret = malloc(retlen + 1); + p = ret; - if (retlen == 0) { - *p = 0; - return; - } + if (retlen == 0) { + *p = 0; + return ret; + } - while (retlen > 0) { + while (retlen > 0) { if (*start == '/' && retlen > 1) { if (start[1] == '/') { do { start++, retlen--; } while (retlen > 1 && start[1] != '\n' && start[1] != '\r'); - start++, retlen--; - continue; + start++, retlen--; + continue; } else if (start[1] == '*') { do { start++, retlen--; } while (retlen > 2 && (start[1] != '*' || start[2] != '/')); start += 3, retlen -= 3; - continue; + continue; } } - *(p++) = *(start++), retlen--; - } - - *p = 0; - return ret; + *(p++) = *(start++), retlen--; + } + + *p = 0; + return ret; } static char *do_eglShaderPatch(const char *source, int length, int *patched_len) { - char *saveptr = NULL; - char *sp; - char *p = NULL; + const char *saveptr = NULL; + char *sp; + char *p = NULL; - if (!length) + if (!length) length = strlen(source); - + *patched_len = 0; int patched_size = length; char *patched = malloc(patched_size + 1); - if (!patched) + if (!patched) return NULL; p = opengl_strtok(source, &length, &saveptr, NULL); for (; p; p = opengl_strtok(0, &length, &saveptr, p)) { - if (!strncmp(p, "lowp", 4) || !strncmp(p, "mediump", 7) || !strncmp(p, "highp", 5)) { + if (!strncmp(p, "lowp", 4) || !strncmp(p, "mediump", 7) + || !strncmp(p, "highp", 5)) { continue; } else if (!strncmp(p, "precision", 9)) { - while ((p = opengl_strtok(0, &length, &saveptr, p)) && !strchr(p, ';')) { - // do nothing - ; - } + while ((p = opengl_strtok(0, &length, &saveptr, p)) + && !strchr(p, ';')) { + // do nothing + ; + } } else { + const char *p2; if (!strncmp(p, "gl_MaxVertexUniformVectors", 26)) { - p = "(gl_MaxVertexUniformComponents / 4)"; + p2 = "(gl_MaxVertexUniformComponents / 4)"; } else if (!strncmp(p, "gl_MaxFragmentUniformVectors", 28)) { - p = "(gl_MaxFragmentUniformComponents / 4)"; + p2 = "(gl_MaxFragmentUniformComponents / 4)"; } else if (!strncmp(p, "gl_MaxVaryingVectors", 20)) { - p = "(gl_MaxVaryingFloats / 4)"; + p2 = "(gl_MaxVaryingFloats / 4)"; + } else { + p2 = p; } - int new_len = strlen(p); + int new_len = strlen(p2); if (*patched_len + new_len > patched_size) { patched_size *= 2; patched = realloc(patched, patched_size + 1); - if (!patched) + if (!patched) return NULL; } - memcpy(patched + *patched_len, p, new_len); + memcpy(patched + *patched_len, p2, new_len); *patched_len += new_len; - } + } } patched[*patched_len] = 0; /* check that we don't leave dummy preprocessor lines */ for (sp = patched; *sp;) { for (; *sp == ' ' || *sp == '\t'; sp++) { - ; // do nothing - } + ; // do nothing + } if (!strncmp(sp, "#define", 7)) { for (p = sp + 7; *p == ' ' || *p == '\t'; p++) { - ; // do nothing - } + ; // do nothing + } if (*p == '\n' || *p == '\r' || *p == '/') { memset(sp, 0x20, 7); } } for (; *sp && *sp != '\n' && *sp != '\r'; sp++) { - ; // do nothing - } + ; // do nothing + } for (; *sp == '\n' || *sp == '\r'; sp++) { - ; // do nothing - } + ; // do nothing + } } return patched; } -static int -shadersrc_gles_to_gl(GLsizei count, const char** string, char **s, const GLint* length, GLint *l) +static int +shadersrc_gles_to_gl(GLsizei count, const char **string, char **s, + const GLint * length, GLint * l) { - int i; - - for(i = 0; i < count; ++i) { - GLint len; - if(length) { - len = length[i]; - if (len < 0) - len = string[i] ? strlen(string[i]) : 0; - } else - len = string[i] ? strlen(string[i]) : 0; - - if(string[i]) { - s[i] = do_eglShaderPatch(string[i], len, &l[i]); - if(!s[i]) { - while(i) { - free(s[--i]); - } - - free(l); - free(s); - return -1; - } - } else { - s[i] = NULL; - l[i] = 0; - } - } - - return 0; + int i; + + for (i = 0; i < count; ++i) { + GLint len; + if (length) { + len = length[i]; + if (len < 0) + len = string[i] ? strlen(string[i]) : 0; + } else + len = string[i] ? strlen(string[i]) : 0; + + if (string[i]) { + s[i] = do_eglShaderPatch(string[i], len, &l[i]); + if (!s[i]) { + while (i) { + free(s[--i]); + } + + free(l); + free(s); + return -1; + } + } else { + s[i] = NULL; + l[i] = 0; + } + } + + return 0; } #ifdef __APPLE__ @@ -1418,41 +1573,91 @@ shadersrc_gles_to_gl(GLsizei count, const char** string, char **s, const GLint* * read texture back right after glTexSubImage2D, thus guarantee a * synchronization. */ -static void mac_dump_texture() +static void mac_dump_texture(void) { - int w, h; - unsigned char *buf; + int w, h; + unsigned char *buf; - /* only handle target=GL_TEXTURE_2D, level=0, format=GL_RGBA, type=GL_UNSIGNED_BYTE */ - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); + /* only handle target=GL_TEXTURE_2D, level=0, format=GL_RGBA, type=GL_UNSIGNED_BYTE */ + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); - if ( w == 0 && h == 0 ) - return; + if (w == 0 && h == 0) + return; - buf = g_malloc( (w*4) * h); /* XXX:need allignment? */ + buf = g_malloc((w * 4) * h); /* XXX:need allignment? */ - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); - g_free(buf); + g_free(buf); } #endif -int do_function_call(ProcessState *process, int func_number, unsigned long *args, char *ret_string) +static int record_fbconfig_set(ProcessState * process, + const GLXFBConfig * fbconfigs, int nconfigs) +{ + int i; + int id; + int previous_entries = 0; + + if (!fbconfigs) + return 0; + + /* Check if we already have a similar set in our tables */ + for (i = 0; i < process->nfbconfig; i++) { + if (process->fbconfigs_max[i] == nconfigs && + !memcmp(fbconfigs, process->fbconfigs[i], + sizeof(GLXFBConfig) * nconfigs)) { + /* No need to store this set as it's identical to another one */ + // XFree(fbconfigs); + + /* Return the identifier of the previously allocated set matching the query */ + id = previous_entries + 1; + return id; + } else + previous_entries += process->fbconfigs_max[i]; + } + + /* Check if we have room for a new set */ + if (process->nfbconfig >= MAX_FBCONFIG) { + fprintf(stderr, + "[%s]:%d Too many FB configs allocated for this process\n", + __FUNCTION__, __LINE__); + // XFree(fbconfigs); + return 0; + } + + /* Store new set - this block should be released using XFree on process exit */ + process->fbconfigs[process->nfbconfig] = fbconfigs; + process->fbconfigs_max[process->nfbconfig] = nconfigs; + process->nfbconfig++; + process->nfbconfig_total += nconfigs; + + id = previous_entries + 1; + return id; +} + +int do_function_call(ProcessState * process, int func_number, + unsigned long *args, char *ret_string) { union gl_ret_type ret; Signature *signature = (Signature *) tab_opengl_calls[func_number]; int ret_type = signature->ret_type; + struct timeval t0, t1; + + if (TRACE_ON(qemu)) { + gettimeofday(&t0, NULL); + } ret.s = NULL; if (display_function_call) { - DEBUGF( "[%d]> %s\n", process->p.process_id, - tab_opengl_calls_name[func_number]); + DEBUGF("[%d]> %s\n", process->p.process_id, + tab_opengl_calls_name[func_number]); } - TRACE( "[%d]> %s\n", process->p.process_id, - tab_opengl_calls_name[func_number]); + TRACE("[%d]> %s\n", process->p.process_id, + tab_opengl_calls_name[func_number]); switch (func_number) { case -1: @@ -1461,12 +1666,20 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case _resize_surface_func: { ClientGLXDrawable client_drawable = to_drawable(args[0]); - QGloSurface *qsurface = get_qsurface_from_client_drawable( - process->current_state, client_drawable); + QGloSurface *qsurface = + get_qsurface_from_client_drawable(process->current_state, + client_drawable); // We have to assume the current context here // since we assume that a drawable must belong to a specific context - resize_surface(process, qsurface, (int)args[1], (int)args[2]); + if (qsurface) + resize_surface(process, qsurface, (int)args[1], (int)args[2]); + else + DEBUGF + ("%s Failed to find surface for client_drawable %p process %p ->current_state %p ->->current_surface %p\n", + "_resize_surface_func", client_drawable, process, + process->current_state, + process->current_state->current_qsurface); break; } @@ -1474,24 +1687,26 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case _render_surface_func: { ClientGLXDrawable client_drawable = to_drawable(args[0]); - QGloSurface *qsurface = get_qsurface_from_client_drawable( - process->current_state, client_drawable); - int bpp = (int)args[1]; + QGloSurface *qsurface = + get_qsurface_from_client_drawable(process->current_state, + client_drawable); + int bpp = (int)args[1]; int stride = (int)args[2]; - char *render_buffer = (char*)args[3]; + char *render_buffer = (char *)args[3]; // DEBUGF( "win: %08x stride: %d buf: %08x cl_dr: %08x qsurf: %08x\n", args[0], args[1], args[2], client_drawable, qsurface); // We have to assume the current context here // since we assume that a drawable must belong to a specific context - render_surface(qsurface, bpp, stride, render_buffer); + if (qsurface) + render_surface(qsurface, bpp, stride, render_buffer); break; } case glXWaitGL_func: { - glFinish(); //glXWaitGL(); + glFinish(); //glXWaitGL(); ret.i = 0; break; } @@ -1506,23 +1721,30 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glXChooseVisual_func: { - ret.i = glXChooseVisualFunc((int *) &args[2]); + ret.i = glXChooseVisualFunc((int *)&args[2]); break; } case glXQueryExtensionsString_func: { - ret.s = supported_glx_extensions();//glXQueryExtensionsString(dpy, 0); + ret.s = supported_glx_extensions(); //glXQueryExtensionsString(dpy, 0); break; } case glXQueryServerString_func: { switch (args[2]) { - case GLX_VENDOR : ret.s = FAKE_GLX_VENDOR; break; - case GLX_VERSION : ret.s = FAKE_GLX_VERSION_STRING; break; - case GLX_EXTENSIONS : ret.s = supported_glx_extensions(); break; - default: ret.s = 0; + case GLX_VENDOR: + ret.s = FAKE_GLX_VENDOR; + break; + case GLX_VERSION: + ret.s = FAKE_GLX_VERSION_STRING; + break; + case GLX_EXTENSIONS: + ret.s = supported_glx_extensions(); + break; + default: + ret.s = 0; } break; } @@ -1530,10 +1752,17 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glXGetClientString_func: { switch (args[1]) { - case GLX_VENDOR : ret.s = FAKE_GLX_VENDOR; break; - case GLX_VERSION : ret.s = FAKE_GLX_VERSION_STRING; break; - case GLX_EXTENSIONS : ret.s = "GLX_ARB_get_proc_address "; break; - default: ret.s = 0; + case GLX_VENDOR: + ret.s = FAKE_GLX_VENDOR; + break; + case GLX_VERSION: + ret.s = FAKE_GLX_VERSION_STRING; + break; + case GLX_EXTENSIONS: + ret.s = "GLX_ARB_get_proc_address "; + break; + default: + ret.s = 0; } break; } @@ -1558,94 +1787,122 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glXCreateContext_func: { - int visualid = (int) args[1]; - int fake_shareList = (int) args[2]; + int visualid = (int)args[1]; + int fake_shareList = (int)args[2]; if (display_function_call) - DEBUGF( "visualid=%d, fake_shareList=%d\n", visualid, - fake_shareList); + DEBUGF("visualid=%d, fake_shareList=%d\n", visualid, + fake_shareList); - GLState *shareListState = get_glstate_for_fake_ctxt(process, fake_shareList); - int fake_ctxt = ++process->next_available_context_number; + GLState *shareListState = + get_glstate_for_fake_ctxt(process, fake_shareList); - ret.i = fake_ctxt; + ret.i = 0; // Work out format flags from visual id int formatFlags = GLO_FF_DEFAULT; - if (visualid>=0 && visualidcontext = glo_context_create(formatFlags, - (GloContext*)shareListState?shareListState->context:0); - - DEBUGF( " created context %p for %08x\n", state, fake_ctxt); + if (visualid >= 0 && visualid < DIM(FBCONFIGS)) + formatFlags = FBCONFIGS[visualid].formatFlags; + + GloContext *context = glo_context_create(formatFlags, + (GloContext *) + shareListState ? + shareListState-> + context : 0); + if (context) { + GLState *state = + _create_context(process, + ++process->next_available_context_number); + if (state) { + state->context = context; + set_context_sharelist(process, state, fake_shareList); + ret.i = state->fake_ctxt; + } else { + DEBUGF("Failed to allocate state context for format %08x\n", + formatFlags); + glo_context_destroy(context); + } + } else { + DEBUGF("Failed to create context for format %08x\n", + formatFlags); + } break; } - case glXCreateNewContext_func: { int client_fbconfig = args[1]; ret.i = 0; - const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig); + const GLXFBConfig *fbconfig = + get_fbconfig(process, client_fbconfig); if (fbconfig) { int fake_shareList = args[3]; - GLState *shareListState = get_glstate_for_fake_ctxt(process, fake_shareList); - - process->next_available_context_number++; - int fake_ctxt = process->next_available_context_number; - ret.i = fake_ctxt; - - DEBUGF( "fake_ctxt = %d\n", fake_ctxt); - - GLState *state = _create_context(process, fake_ctxt, fake_shareList); - state->context = glo_context_create(fbconfig->formatFlags, - shareListState?shareListState->context:0); // FIXME GW get from fbconfig + GLState *shareListState = + get_glstate_for_fake_ctxt(process, fake_shareList); + + GloContext *context = glo_context_create(fbconfig->formatFlags, + (GloContext *) shareListState ? shareListState->context : 0); // FIXME GW get from fbconfig + if (context) { + GLState *state = + _create_context(process, + ++process-> + next_available_context_number); + if (state) { + state->context = context; + set_context_sharelist(process, state, fake_shareList); + ret.i = state->fake_ctxt; + } else { + DEBUGF + ("Failed to allocate state context for format %08x", + fbconfig->formatFlags); + glo_context_destroy(context); + } + } else { + DEBUGF("Failed to create context for format %08x", + fbconfig->formatFlags); + } } break; } case glXCopyContext_func: { - DEBUGF( " glXCopyContext not supported (does anything use it?)\n"); + DEBUGF(" glXCopyContext not supported (does anything use it?)\n"); break; } case glXDestroyContext_func: { - int fake_ctxt = (int) args[1]; + int fake_ctxt = (int)args[1]; if (display_function_call) - DEBUGF( "fake_ctxt=%d\n", fake_ctxt); + DEBUGF("fake_ctxt=%d\n", fake_ctxt); int i; - for (i = 0; i < process->nb_states; i ++) { + for (i = 0; i < process->nb_states; i++) { if (process->glstates[i]->fake_ctxt == fake_ctxt) { - /*XXX: DestroyContext should not switch current context, or - * else guest still try to access it and cause qemu - * segfalt. But not sure if any corner case, so comment it - * for now and will remove it completely in future. - */ + /*XXX: DestroyContext should not switch current context, or + * else guest still try to access it and cause qemu + * segfalt. But not sure if any corner case, so comment it + * for now and will remove it completely in future. + */ // this was our GLState... // process->current_state = &process->default_state; - int fake_shareList = - process->glstates[i]->fake_shareList; + int fake_shareList = process->glstates[i]->fake_shareList; process->glstates[i]->ref--; if (process->glstates[i]->ref == 0) { - DEBUGF( - "destroy_gl_state fake_ctxt = %d\n", - process->glstates[i]->fake_ctxt); + DEBUGF("destroy_gl_state fake_ctxt = %d\n", + process->glstates[i]->fake_ctxt); destroy_gl_state(process->glstates[i]); g_free(process->glstates[i]); memmove(&process->glstates[i], &process->glstates[i + 1], (process->nb_states - i - 1) * sizeof(GLState *)); - process->nb_states --; + process->nb_states--; } if (fake_shareList) { @@ -1654,18 +1911,16 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args fake_shareList) { process->glstates[i]->ref--; if (process->glstates[i]->ref == 0) { - DEBUGF( - "destroy_gl_state fake_sharelist fake_ctxt = %d\n", - process->glstates[i]-> - fake_ctxt); - destroy_gl_state(process-> - glstates[i]); + DEBUGF + ("destroy_gl_state fake_sharelist fake_ctxt = %d\n", + process->glstates[i]->fake_ctxt); + destroy_gl_state(process->glstates[i]); g_free(process->glstates[i]); memmove(&process->glstates[i], &process->glstates[i + 1], (process->nb_states - i - 1) * sizeof(GLState *)); - process->nb_states --; + process->nb_states--; } break; } @@ -1680,11 +1935,13 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glXQueryVersion_func: { - int *major = (int *) args[1]; - int *minor = (int *) args[2]; + int *major = (int *)args[1]; + int *minor = (int *)args[2]; //ret.i = glXQueryVersion(dpy, (int *) args[1], (int *) args[2]); - if (major) *major=FAKE_GLX_VERSION_MAJOR; - if (minor) *minor=FAKE_GLX_VERSION_MINOR; + if (major) + *major = FAKE_GLX_VERSION_MAJOR; + if (minor) + *minor = FAKE_GLX_VERSION_MINOR; ret.i = True; break; } @@ -1692,27 +1949,27 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glGetString_func: { switch (args[0]) { - case GL_VENDOR: + case GL_VENDOR: ret.s = FAKE_GL_VENDOR; - break; - case GL_RENDERER: + break; + case GL_RENDERER: ret.s = FAKE_GL_RENDERER; - break; - case GL_VERSION: + break; + case GL_VERSION: ret.s = FAKE_GL_VERSION; - break; - case GL_EXTENSIONS: + break; + case GL_EXTENSIONS: ret.s = compute_gl_extensions(); - break; - case GL_SHADING_LANGUAGE_VERSION: - if(FAKE_GL_MAJOR < 2) { - ret.s = ""; - break; + break; + case GL_SHADING_LANGUAGE_VERSION: + if (FAKE_GL_MAJOR < 2) { + ret.s = ""; + break; } - // Fall through. - default: - ret.s = (char *) glGetString(args[0]); - break; + // Fall through. + default: + ret.s = (char *)glGetString(args[0]); + break; } break; } @@ -1720,70 +1977,85 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glXMakeCurrent_func: { ClientGLXDrawable client_drawable = to_drawable(args[1]); - int fake_ctxt = (int) args[2]; + int fake_ctxt = (int)args[2]; GLState *glstate = NULL; - DEBUGF( "Makecurrent: fake_ctx=%d client_drawable=%08x\n", fake_ctxt, client_drawable); + DEBUGF("Makecurrent: fake_ctx=%d client_drawable=%08x\n", fake_ctxt, + client_drawable); if (client_drawable == 0 && fake_ctxt == 0) { /* Release context */ - if(process->current_state->current_qsurface) { - if(process->current_state->current_qsurface->type != SURFACE_PIXMAP) + if (process->current_state->current_qsurface) { + if (process->current_state->current_qsurface->type != + SURFACE_PIXMAP) process->current_state->current_qsurface->ref--; else - unbind_qsurface(process->current_state, process->current_state->current_qsurface); + unbind_qsurface(process->current_state, + process->current_state-> + current_qsurface); } process->current_state = &process->default_state; - DEBUGF( " --release\n"); + DEBUGF(" --release\n"); glo_surface_makecurrent(0); - } else { /* Lookup GLState struct for this context */ + } else { /* Lookup GLState struct for this context */ glstate = get_glstate_for_fake_ctxt(process, fake_ctxt); if (!glstate) { - DEBUGF( " --invalid fake_ctxt (%d)!\n", fake_ctxt); + DEBUGF(" --invalid fake_ctxt (%d)!\n", fake_ctxt); } else { - if(!set_current_qsurface(glstate, client_drawable) && - !link_qsurface(process, glstate, client_drawable) ) { - // If there is no surface, create one. - QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); - qsurface->surface = glo_surface_create(4, 4, - glstate->context); - qsurface->client_drawable = client_drawable; - qsurface->ref = 1; - qsurface->type = SURFACE_WINDOW; - qsurface->status = SURFACE_ACTIVE; - - bind_qsurface(glstate, qsurface); - DEBUGF( " --Client drawable not found, create new surface: %16x %16lx\n", (unsigned int)qsurface, (unsigned long int)client_drawable); - - } - else { - DEBUGF( " --Client drawable found, using surface: %16x %16lx\n", (unsigned int)glstate->current_qsurface, (unsigned long int)client_drawable); + if (!set_current_qsurface(glstate, client_drawable) && + !link_qsurface(process, glstate, client_drawable)) { + // If there is no surface, create one. + QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); + qsurface->surface = glo_surface_create(4, 4, + glstate-> + context); + qsurface->client_drawable = client_drawable; + qsurface->ref = 1; + qsurface->type = SURFACE_WINDOW; + qsurface->status = SURFACE_ACTIVE; + + bind_qsurface(glstate, qsurface); + DEBUGF + (" --Client drawable not found, create new surface: %p %16lx\n", + qsurface, (unsigned long int)client_drawable); + } else { + DEBUGF + (" --Client drawable found, using surface: %p %16lx\n", + glstate->current_qsurface, + (unsigned long int)client_drawable); } #if 0 /*Test old surface contents */ int reset_texture = 0; GLState *old_glstate = NULL; /* Switch from pixmap */ - if (process->current_state->current_qsurface && SURFACE_PIXMAP == process->current_state->current_qsurface->type ) - { - glo_surface_updatecontents(process->current_state->current_qsurface->surface); + if (process->current_state->current_qsurface + && SURFACE_PIXMAP == + process->current_state->current_qsurface->type) { + glo_surface_updatecontents(process->current_state-> + current_qsurface->surface); reset_texture = 1; old_glstate = process->current_state; } - fprintf(stderr, "edwin:MakeCurrent: drawable=0x%x,qsurface=%p.\n", client_drawable, glstate->current_qsurface); + fprintf(stderr, + "edwin:MakeCurrent: drawable=0x%x,qsurface=%p.\n", + client_drawable, glstate->current_qsurface); #endif /* Switch in pixmap surface */ - if (glstate->current_qsurface && SURFACE_PIXMAP == glstate->current_qsurface->type ) - { + if (glstate->current_qsurface + && SURFACE_PIXMAP == glstate->current_qsurface->type) { /* Release it if the surface is used as texture target */ - glo_surface_release_texture(glstate->current_qsurface); + glo_surface_release_texture(glstate->current_qsurface-> + surface); } process->current_state = glstate; - ret.i = glo_surface_makecurrent(glstate->current_qsurface->surface); + ret.i = + glo_surface_makecurrent(glstate->current_qsurface-> + surface); /* if (reset_texture)*/ /* glo_surface_as_texture(process->current_state->context, old_glstate->current_qsurface->surface);*/ } @@ -1810,7 +2082,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glXGetConfig_func: { int visualid = args[1]; - ret.i = glXGetConfigFunc(visualid, args[2], (int *) args[3]); + ret.i = glXGetConfigFunc(visualid, args[2], (int *)args[3]); break; } @@ -1819,9 +2091,9 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int visualid = args[1]; int n = args[2]; int i; - int *attribs = (int *) args[3]; - int *values = (int *) args[4]; - int *res = (int *) args[5]; + int *attribs = (int *)args[3]; + int *values = (int *)args[4]; + int *res = (int *)args[5]; for (i = 0; i < n; i++) { res[i] = glXGetConfigFunc(visualid, attribs[i], &values[i]); @@ -1837,57 +2109,45 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glXQueryExtension_func: { - int *errorBase = (int *) args[1]; - int *eventBase = (int *) args[2]; - if (errorBase) *errorBase = 0; /* FIXME GW */ - if (eventBase) *eventBase = 0; /* FIXME GW */ + int *errorBase = (int *)args[1]; + int *eventBase = (int *)args[2]; + if (errorBase) + *errorBase = 0; /* FIXME GW */ + if (eventBase) + *eventBase = 0; /* FIXME GW */ ret.i = True; break; } case glXChooseFBConfig_func: { - if (process->nfbconfig >= MAX_FBCONFIG) { - fprintf(stderr, "[%s]:%d Request FB configs error, excceed the MAX FBCONFIG of one process, return NULL!\n", __FUNCTION__, __LINE__); - *(int *) args[3] = 0; - ret.i = 0; - } else { - const GLXFBConfig *fbconfigs = - glXChooseFBConfigFunc(args[1], (int *) args[2], (int *) args[3]); - if (fbconfigs) { - process->fbconfigs[process->nfbconfig] = fbconfigs; - process->fbconfigs_max[process->nfbconfig] = - *(int *) args[3]; - process->nfbconfig++; - ret.i = 1 + process->nfbconfig_total; - process->nfbconfig_total += - process->fbconfigs_max[process->nfbconfig]; - } else { - ret.i = 0; - } - } + /* Retrieve array of FB configs matching our contraints */ + const GLXFBConfig *fbconfigs = + glXChooseFBConfigFunc(args[1], (int *)args[2], (int *)args[3]); + + /* Record this in our tables and return a client-side identifier for the first entry in the array */ + ret.i = record_fbconfig_set(process, fbconfigs, *(int *)args[3]); + + /* Zero indicates failure */ + if (ret.i == 0) + *(int *)args[3] = 0; + break; } + case glXGetFBConfigs_func: { - if (process->nfbconfig == MAX_FBCONFIG) { - *(int *) args[2] = 0; - ret.i = 0; - } else { - const GLXFBConfig *fbconfigs = - glXGetFBConfigsFunc(args[1], (int *) args[2]); - if (fbconfigs) { - process->fbconfigs[process->nfbconfig] = fbconfigs; - process->fbconfigs_max[process->nfbconfig] = - *(int *) args[2]; - process->nfbconfig++; - ret.i = 1 + process->nfbconfig_total; - process->nfbconfig_total += - process->fbconfigs_max[process->nfbconfig]; - } else { - ret.i = 0; - } - } + /* Retrieve array of available FB configs */ + const GLXFBConfig *fbconfigs = + glXGetFBConfigsFunc(args[1], (int *)args[2]); + + /* Record this in our tables and return a client-side identifier for the first entry in the array */ + ret.i = record_fbconfig_set(process, fbconfigs, *(int *)args[2]); + + /* Zero indicates failure */ + if (ret.i == 0) + *(int *)args[2] = 0; + break; } case glXGetFBConfigAttrib_func: @@ -1895,11 +2155,12 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int client_fbconfig = args[1]; ret.i = 0; - const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig); + const GLXFBConfig *fbconfig = + get_fbconfig(process, client_fbconfig); if (fbconfig) ret.i = - glXGetFBConfigAttribFunc(fbconfig, args[2], (int *) args[3]); + glXGetFBConfigAttribFunc(fbconfig, args[2], (int *)args[3]); break; } @@ -1908,15 +2169,17 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int client_fbconfig = args[1]; int n = args[2]; int i; - int *attribs = (int *) args[3]; - int *values = (int *) args[4]; - int *res = (int *) args[5]; - const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig); + int *attribs = (int *)args[3]; + int *values = (int *)args[4]; + int *res = (int *)args[5]; + const GLXFBConfig *fbconfig = + get_fbconfig(process, client_fbconfig); for (i = 0; i < n; i++) { if (fbconfig) { res[i] = - glXGetFBConfigAttribFunc(fbconfig, attribs[i], &values[i]); + glXGetFBConfigAttribFunc(fbconfig, attribs[i], + &values[i]); } else { res[i] = 0; } @@ -1925,24 +2188,24 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args } case glXQueryContext_func: { - DEBUGF( "glXQueryContext not implemented\n"); + DEBUGF("glXQueryContext not implemented\n"); ret.i = 0; -#if 0 //GW +#if 0 //GW GET_EXT_PTR(int, glXQueryContext, (Display *, GLXContext, int, int *)); - int fake_ctxt = (int) args[1]; + int fake_ctxt = (int)args[1]; if (display_function_call) - DEBUGF( "fake_ctx=%i\n", fake_ctxt); + DEBUGF("fake_ctx=%i\n", fake_ctxt); GLXContext ctxt = get_association_fakecontext_glxcontext(process, fake_ctxt); if (ctxt == NULL) { - DEBUGF( "invalid fake_ctxt (%i) !\n", fake_ctxt); + DEBUGF("invalid fake_ctxt (%i) !\n", fake_ctxt); ret.i = 0; } else { ret.i = ptr_func_glXQueryContext(dpy, ctxt, args[2], - (int *) args[3]); + (int *)args[3]); } #endif break; @@ -1952,26 +2215,24 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args { // TODO GW one of: // GLX_WIDTH, GLX_HEIGHT, GLX_PRESERVED_CONTENTS, GLX_LARGEST_PBUFFER, GLX_FBCONFIG_ID - DEBUGF( "FIXME: glXQueryDrawable not implemented\n"); + DEBUGF("FIXME: glXQueryDrawable not implemented\n"); ret.i = 0; -#if 0 //GW +#if 0 //GW GET_EXT_PTR(void, glXQueryDrawable, (Display *, GLXDrawable, int, int *)); ClientGLXDrawable client_drawable = to_drawable(args[1]); GLXDrawable drawable = - get_association_clientdrawable_serverdrawable( - glstate, client_drawable); + get_association_clientdrawable_serverdrawable(glstate, + client_drawable); if (display_function_call) - DEBUGF( "client_drawable=%p\n", - client_drawable); + DEBUGF("client_drawable=%p\n", client_drawable); if (!drawable) - DEBUGF( "invalid client_drawable (%p) !\n", - client_drawable); + DEBUGF("invalid client_drawable (%p) !\n", client_drawable); else ptr_func_glXQueryDrawable(dpy, drawable, - args[2], (int *) args[3]); + args[2], (int *)args[3]); #endif break; } @@ -1980,20 +2241,21 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int client_fbconfig = args[1]; ret.i = 0; - const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig); + const GLXFBConfig *fbconfig = + get_fbconfig(process, client_fbconfig); if (fbconfig) { // we tread visualid as the index into the fbconfigs array ret.i = &FBCONFIGS[0] - fbconfig; if (display_function_call) - DEBUGF( "visualid = %d\n", ret.i); + DEBUGF("visualid = %d\n", ret.i); } break; } case glXSwapIntervalSGI_func: { /*GET_EXT_PTR(int, glXSwapIntervalSGI, (int)); - ret.i = ptr_func_glXSwapIntervalSGI(args[0]);*/ + ret.i = ptr_func_glXSwapIntervalSGI(args[0]); */ ret.i = 0; break; } @@ -2002,7 +2264,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args { // if (display_function_call) //DEBUGF( "glXGetProcAddress %s ", (char *) args[0]); - ret.i = glo_getprocaddress((const char *) args[0]) != NULL; + ret.i = glo_getprocaddress((const char *)args[0]) != NULL; // DEBUGF( " == %08x\n", ret.i); ret.i = 0; break; @@ -2011,16 +2273,15 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glXGetProcAddress_global_fake_func: { int nbElts = args[0]; - char *huge_buffer = (char *) args[1]; - char *result = (char *) args[2]; + char *huge_buffer = (char *)args[1]; + char *result = (char *)args[2]; int i; for (i = 0; i < nbElts; i++) { int len = strlen(huge_buffer); //DEBUGF( "glXGetProcAddress_global %s ", (char *)huge_buffer); result[i] = - glo_getprocaddress((const char *) huge_buffer) != - NULL; + glo_getprocaddress((const char *)huge_buffer) != NULL; huge_buffer += len + 1; } break; @@ -2030,40 +2291,52 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int client_fbconfig = args[1]; ret.i = 0; - const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig); + const GLXFBConfig *fbconfig = + get_fbconfig(process, client_fbconfig); if (fbconfig) { - /* Create a light-weight context just for creating surface */ - GloContext *context = __glo_context_create(fbconfig->formatFlags); - - /* glXPixmap same as input Pixmap */ - ClientGLXDrawable client_drawable = to_drawable(args[2]); - - QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); - - /* get the width and height */ - int width, height; - glo_geometry_get_from_glx((int*)args[3], &width, &height); - - DEBUGF( "glXCreatePixmap: %dX%d.\n", width, height); - qsurface->surface = glo_surface_create(width, height, context); - qsurface->client_drawable = client_drawable; - qsurface->type = SURFACE_PIXMAP; - qsurface->status = SURFACE_PENDING; - /* qsurface->ref = 1;*/ - - /* Keep this surface, will link it with context in MakeCurrent */ - keep_qsurface(process, qsurface); - - /* If this pixmap is linked as texture previously */ - if (link_drawable(process, client_drawable)) - glo_surface_as_texture(process->current_state->context, - qsurface->surface, qsurface->type); - - - ret.i = client_drawable; - + GloContext *context = + __glo_context_create(fbconfig->formatFlags); + if (context) { + /* glXPixmap same as input Pixmap */ + ClientGLXDrawable client_drawable = to_drawable(args[2]); + + QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); + if (qsurface) { + /* get the width and height */ + int width, height; + glo_geometry_get_from_glx((int *)args[3], &width, + &height); + + DEBUGF("glXCreatePixmap: %dX%d.\n", width, height); + qsurface->surface = + glo_surface_create(width, height, context); + if (qsurface->surface) { + qsurface->client_drawable = client_drawable; + qsurface->type = SURFACE_PIXMAP; + qsurface->status = SURFACE_PENDING; + qsurface_pixmap_ref(qsurface); + + /* Keep this surface, will link it with context in MakeCurrent */ + keep_qsurface(process, qsurface); + + /* If this pixmap is linked as texture previously */ + if (link_drawable(process, client_drawable)) + glo_surface_as_texture(process->current_state-> + context, + qsurface->surface, + qsurface->type); + + ret.i = (int)client_drawable; + } else { + free(qsurface); + glo_context_destroy(context); + } + } else { + glo_context_destroy(context); + } + } } break; } @@ -2071,125 +2344,130 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args { /* glXPixmap same as input Pixmap */ ClientGLXDrawable client_drawable = to_drawable(args[1]); - QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); - if ( qsurface && - qsurface != process->current_state->current_qsurface && - qsurface->glstate == NULL && - qsurface->type == SURFACE_PIXMAP ) - { - glo_surface_destroy(qsurface->surface); - g_free(qsurface); - } + QGloSurface *qsurface = + find_qsurface_from_client_drawable(process, client_drawable); + qsurface_pixmap_unref(qsurface); break; } case glEGLImageTargetTexture2DOES_fake_func: { int target = args[0]; ClientGLXDrawable client_drawable = to_drawable(args[1]); - QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); + QGloSurface *qsurface = + find_qsurface_from_client_drawable(process, client_drawable); - /* Only support GL_TEXTURE_2D according to spec */ - if ( target == GL_TEXTURE_2D ) + /* Only support GL_TEXTURE_2D according to spec */ + if (target == GL_TEXTURE_2D) add_pixmap_texture_mapping(process->current_state, - process->current_state->bindTexture2D, - client_drawable); - - if ( !qsurface ) - { - if ( !keep_drawable(process, client_drawable) ) - { - DEBUGF( "No space to store drawable for ImageTargetTexture. Need call CreatePixmapSurface to free them.\n"); + process->current_state-> + bindTexture2D, client_drawable); + + if (!qsurface) { + if (!keep_drawable(process, client_drawable)) { + DEBUGF + ("No space to store drawable for ImageTargetTexture. Need call CreatePixmapSurface to free them.\n"); break; } + } else + glo_surface_as_texture(process->current_state->context, + qsurface->surface, qsurface->type); + + break; + } + case glXBindTexImageARB_fake_func: + { + ClientGLXDrawable client_drawable = to_drawable(args[1]); + QGloSurface *qsurface = + find_qsurface_from_client_drawable(process, client_drawable); + ret.i = 0; + + if (qsurface) { + add_pixmap_texture_mapping(process->current_state, + process->current_state-> + bindTexture2D, client_drawable); + glo_surface_as_texture(process->current_state->context, + qsurface->surface, qsurface->type); + ret.i = 1; + } else + DEBUGF("Not found pbuffer surface for BindTexImage!\n"); + + break; + } + case glXReleaseTexImageARB_fake_func: + { + ClientGLXDrawable client_drawable = to_drawable(args[1]); + QGloSurface *qsurface = + find_qsurface_from_client_drawable(process, client_drawable); + + if (qsurface) { + remove_pixmap_texture_mapping(process->current_state, + client_drawable); + glo_surface_release_texture(qsurface->surface); } - else - glo_surface_as_texture(process->current_state->context, qsurface->surface, qsurface->type); - - break; - } - case glXBindTexImageARB_fake_func: - { - ClientGLXDrawable client_drawable = to_drawable(args[1]); - QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); - ret.i = 0; - - - if ( qsurface ) - { - add_pixmap_texture_mapping(process->current_state, - process->current_state->bindTexture2D, - client_drawable); - glo_surface_as_texture(process->current_state->context, qsurface->surface, qsurface->type); - ret.i = 1; - } - else - DEBUGF( "Not found pbuffer surface for BindTexImage!\n"); - - break; - } - case glXReleaseTexImageARB_fake_func: - { - ClientGLXDrawable client_drawable = to_drawable(args[1]); - QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); - - if ( qsurface ) - { - remove_pixmap_texture_mapping(process->current_state, - client_drawable); - glo_surface_release_texture(qsurface->surface); - } - - break; - } - case glXCreatePbuffer_func: - { - int client_fbconfig = args[1]; - - ret.i = 0; - const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig); - - if (fbconfig) { - - /* Create a light-weight context just for creating surface */ - GloContext *context = __glo_context_create(fbconfig->formatFlags); - - QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); - - /* get the width and height */ - int width, height; - glo_geometry_get_from_glx((int*)args[2], &width, &height); - - DEBUGF( "glXCreatePbuffer: %dX%d.\n", width, height); - qsurface->surface = glo_surface_create(width, height, context); - /* Use GloSurface handler as no input client_drawable, and - * keep only low 32bit of handler on x86_64 host. */ - qsurface->client_drawable = (int)qsurface->surface; - qsurface->type = SURFACE_PBUFFER; - qsurface->status = SURFACE_PENDING; - /* qsurface->ref = 1;*/ - - /* Keep this surface, will link it with context in MakeCurrent */ - keep_qsurface(process, qsurface); - - ret.i = qsurface->client_drawable; - - } - break; - } - case glXDestroyPbuffer_func: - { + + break; + } + case glXCreatePbuffer_func: + { + int client_fbconfig = args[1]; + + ret.i = 0; + const GLXFBConfig *fbconfig = + get_fbconfig(process, client_fbconfig); + + if (fbconfig) { + + /* Create a light-weight context just for creating surface */ + GloContext *context = + __glo_context_create(fbconfig->formatFlags); + if (context) { + QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); + if (qsurface) { + /* get the width and height */ + int width, height; + glo_geometry_get_from_glx((int *)args[2], &width, + &height); + + DEBUGF("glXCreatePbuffer: %dX%d.\n", width, height); + qsurface->surface = + glo_surface_create(width, height, context); + if (qsurface->surface) { + /* Use GloSurface handler as no input client_drawable, and + * keep only low 32bit of handler on x86_64 host. */ + qsurface->client_drawable = + (ClientGLXDrawable) (long)qsurface->surface; + qsurface->type = SURFACE_PBUFFER; + qsurface->status = SURFACE_PENDING; + /* qsurface->ref = 1; */ + + /* Keep this surface, will link it with context in MakeCurrent */ + keep_qsurface(process, qsurface); + + ret.i = qsurface->client_drawable; + } else { + free(qsurface); + glo_context_destroy(context); + } + } else { + glo_context_destroy(context); + } + } + } + break; + } + case glXDestroyPbuffer_func: + { ClientGLXDrawable client_drawable = to_drawable(args[1]); - QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); - if ( qsurface && - qsurface != process->current_state->current_qsurface && - qsurface->glstate == NULL && - qsurface->type == SURFACE_PBUFFER ) - { + QGloSurface *qsurface = + find_qsurface_from_client_drawable(process, client_drawable); + if (qsurface && qsurface != process->current_state->current_qsurface + && qsurface->glstate == NULL + && qsurface->type == SURFACE_PBUFFER) { glo_surface_destroy(qsurface->surface); g_free(qsurface); } break; - } + } /* Begin of texture stuff */ case glBindTexture_func: @@ -2199,46 +2477,48 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args unsigned int client_texture = args[1]; unsigned int server_texture; - if(((int)client_texture) < 0) - { - fprintf(stderr, "glBindTexture got invalid texture ID, do nothing!\n"); - break; - } + if (((int)client_texture) < 0) { + fprintf(stderr, + "glBindTexture got invalid texture ID, do nothing!\n"); + break; + } if (client_texture == 0) { glBindTexture(target, 0); } else { alloc_value(process->current_state->textureAllocator, client_texture); + alloc_space(process->current_state->tabTextures, client_texture, 1); server_texture = - process->current_state->tabTextures[client_texture]; + process->current_state->tabTextures->values[client_texture]; if (server_texture == 0) { glGenTextures(1, &server_texture); - process->current_state->tabTextures[client_texture] = + process->current_state->tabTextures->values[client_texture] = server_texture; } glBindTexture(target, server_texture); } - if ( target == GL_TEXTURE_2D ) { + if (target == GL_TEXTURE_2D) { QGloSurface *qsurface = NULL; ClientGLXDrawable drawable = find_pixmap_texture(process->current_state, client_texture); - if ( drawable ) - { - qsurface = find_qsurface_from_client_drawable(process, drawable); + if (drawable) { + qsurface = + find_qsurface_from_client_drawable(process, drawable); - if ( qsurface ) - { - glo_surface_as_texture(process->current_state->context, qsurface->surface, qsurface->type); - /*fprintf(stderr, "edwin:bindtexture: drawable=0x%x,qsurface=%p.\n", drawable, qsurface);*/ + if (qsurface) { + glo_surface_as_texture(process->current_state->context, + qsurface->surface, + qsurface->type); + /*fprintf(stderr, "edwin:bindtexture: drawable=0x%x,qsurface=%p.\n", drawable, qsurface); */ } } process->current_state->bindTexture2D = client_texture; } - break; + break; } case glGenTextures_fake_func: @@ -2253,9 +2533,10 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args clientTabTextures); //ptr_func_glGenTextures(n, serverTabTextures); - glGenTextures(n, serverTabTextures); + glGenTextures(n, serverTabTextures); for (i = 0; i < n; i++) { - process->current_state->tabTextures[clientTabTextures[i]] = + alloc_space(process->current_state->tabTextures, clientTabTextures[i], 0); + process->current_state->tabTextures->values[clientTabTextures[i]] = serverTabTextures[i]; } @@ -2264,14 +2545,13 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args break; } - case glDeleteTextures_func: { //GET_EXT_PTR(void, glDeleteTextures, // (GLsizei n, const GLuint *textures)); int i; int n = args[0]; - unsigned int *clientTabTextures = (unsigned int *) args[1]; + unsigned int *clientTabTextures = (unsigned int *)args[1]; delete_range(process->current_state->textureAllocator, n, clientTabTextures); @@ -2283,51 +2563,50 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args get_server_texture(process, clientTabTextures[i]); } //ptr_func_glDeleteTextures(n, serverTabTextures); - glDeleteTextures(n, serverTabTextures); + glDeleteTextures(n, serverTabTextures); for (i = 0; i < n; i++) { - process->current_state->tabTextures[clientTabTextures[i]] = 0; + free_space(process->current_state->tabTextures, clientTabTextures[i]); } g_free(serverTabTextures); - for ( i = 0; i < n; i++ ) - { - del_pixmap_texture_mapping(process->current_state, clientTabTextures[i]); + for (i = 0; i < n; i++) { + del_pixmap_texture_mapping(process->current_state, + clientTabTextures[i]); } - break; + break; } case glPrioritizeTextures_func: { GET_EXT_PTR(void, glPrioritizeTextures, - (GLsizei n, const GLuint *textures, - const GLclampf *priorities)); + (GLsizei n, const GLuint * textures, + const GLclampf * priorities)); int i; int n = args[0]; - unsigned int *textures = (unsigned int *) args[1]; + unsigned int *textures = (unsigned int *)args[1]; for (i = 0; i < n; i++) { textures[i] = get_server_texture(process, textures[i]); } ptr_func_glPrioritizeTextures(n, textures, - (const GLclampf *) args[2]); + (const GLclampf *)args[2]); break; } case glAreTexturesResident_func: { GET_EXT_PTR(void, glAreTexturesResident, - (GLsizei n, const GLuint *textures, - GLboolean *residences)); + (GLsizei n, const GLuint * textures, + GLboolean * residences)); int i; int n = args[0]; - unsigned int *textures = (unsigned int *) args[1]; + unsigned int *textures = (unsigned int *)args[1]; for (i = 0; i < n; i++) { textures[i] = get_server_texture(process, textures[i]); } - ptr_func_glAreTexturesResident(n, textures, - (GLboolean *) args[2]); + ptr_func_glAreTexturesResident(n, textures, (GLboolean *) args[2]); break; } @@ -2339,8 +2618,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args unsigned int server_texture = get_server_texture(process, client_texture); if (server_texture) - // ret.c = ptr_func_glIsTexture(server_texture); - ret.c = glIsTexture(server_texture); + // ret.c = ptr_func_glIsTexture(server_texture); + ret.c = glIsTexture(server_texture); else ret.c = 0; break; @@ -2408,8 +2687,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args unsigned int first_client = args[0]; int n = args[1]; - unsigned int first_server = - get_server_list(process, first_client); + unsigned int first_server = get_server_list(process, first_client); for (i = 0; i < n; i++) { if (get_server_list(process, first_client + i) != first_server + i) @@ -2425,7 +2703,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args } for (i = 0; i < n; i++) { - process->current_state->tabLists[first_client + i] = 0; + free_space(process->current_state->tabLists, first_client + i); } delete_consecutive_values(process->current_state->listAllocator, first_client, n); @@ -2443,7 +2721,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args alloc_range(process->current_state->listAllocator, n, NULL); for (i = 0; i < n; i++) { - process->current_state->tabLists[client_first + i] = + alloc_space(process->current_state->tabLists, client_first + i, 0); + process->current_state->tabLists->values[client_first + i] = server_first + i; } } @@ -2460,7 +2739,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args if (server_list == 0) { server_list = glGenLists(1); - process->current_state->tabLists[client_list] = server_list; + alloc_space(process->current_state->tabLists, client_list, 0); + process->current_state->tabLists->values[client_list] = server_list; } glNewList(server_list, mode); break; @@ -2480,7 +2760,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int i; int n = args[0]; int type = args[1]; - const GLvoid *lists = (const GLvoid *) args[2]; + const GLvoid *lists = (const GLvoid *)args[2]; int *new_lists = g_malloc(sizeof(int) * n); for (i = 0; i < n; i++) { @@ -2492,7 +2772,6 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args break; } - /* End of list stuff */ /* Begin of buffer stuff */ @@ -2525,7 +2804,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args ptr_func_glGenBuffersARB(n, serverTabBuffers); for (i = 0; i < n; i++) { - process->current_state->tabBuffers[clientTabBuffers[i]] = + alloc_space(process->current_state->tabBuffers, clientTabBuffers[i], 0); + process->current_state->tabBuffers->values[clientTabBuffers[i]] = serverTabBuffers[i]; } @@ -2534,13 +2814,12 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args break; } - case glDeleteBuffersARB_func: { GET_EXT_PTR(void, glDeleteBuffersARB, (int, int *)); int i; int n = args[0]; - unsigned int *clientTabBuffers = (unsigned int *) args[1]; + unsigned int *clientTabBuffers = (unsigned int *)args[1]; delete_range(process->current_state->bufferAllocator, n, clientTabBuffers); @@ -2553,7 +2832,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args } ptr_func_glDeleteBuffersARB(n, serverTabBuffers); for (i = 0; i < n; i++) { - process->current_state->tabBuffers[clientTabBuffers[i]] = 0; + free_space(process->current_state->tabBuffers, clientTabBuffers[i]); } g_free(serverTabBuffers); break; @@ -2581,60 +2860,60 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int i; int acc_length = 0; GLcharARB **tab_prog = g_malloc(size * sizeof(GLcharARB *)); - int *tab_length = (int *) args[3]; + int *tab_length = (int *)args[3]; for (i = 0; i < size; i++) { tab_prog[i] = ((GLcharARB *) args[2]) + acc_length; acc_length += tab_length[i]; } - ptr_func_glShaderSourceARB(args[0], args[1], tab_prog, - tab_length); + ptr_func_glShaderSourceARB(args[0], args[1], tab_prog, tab_length); g_free(tab_prog); break; } case glShaderSource_fake_func: - { - GET_EXT_PTR(void, glShaderSource, (int, int, char **, void *)); - int size = args[1]; - int i; - int acc_length = 0; - GLcharARB **tab_prog = g_malloc(size * sizeof(GLcharARB *)); - int *tab_length = (int *) args[3]; - - char **tab_prog_new; - GLint *tab_length_new; + { + GET_EXT_PTR(void, glShaderSource, (int, int, char **, void *)); + int size = args[1]; + int i; + int acc_length = 0; + GLcharARB **tab_prog = g_malloc(size * sizeof(GLcharARB *)); + int *tab_length = (int *)args[3]; - tab_prog_new = malloc(args[1]* sizeof(char*)); - tab_length_new = malloc(args[1]* sizeof(GLint)); + char **tab_prog_new; + GLint *tab_length_new; - memset(tab_prog_new, 0, args[1] * sizeof(char*)); - memset(tab_length_new, 0, args[1] * sizeof(GLint)); + tab_prog_new = malloc(args[1] * sizeof(char *)); + tab_length_new = malloc(args[1] * sizeof(GLint)); + memset(tab_prog_new, 0, args[1] * sizeof(char *)); + memset(tab_length_new, 0, args[1] * sizeof(GLint)); - for (i = 0; i < size; i++) { - tab_prog[i] = ((GLcharARB *) args[2]) + acc_length; - acc_length += tab_length[i]; - } + for (i = 0; i < size; i++) { + tab_prog[i] = ((GLcharARB *) args[2]) + acc_length; + acc_length += tab_length[i]; + } - shadersrc_gles_to_gl(args[1], tab_prog, tab_prog_new, tab_length, tab_length_new); + shadersrc_gles_to_gl(args[1], (const char **)tab_prog, tab_prog_new, + tab_length, tab_length_new); - if (!tab_prog_new || !tab_length_new) - break; + if (!tab_prog_new || !tab_length_new) + break; - ptr_func_glShaderSource(args[0], args[1], tab_prog_new, tab_length_new); + ptr_func_glShaderSource(args[0], args[1], tab_prog_new, + tab_length_new); - for (i = 0; i < args[1]; i++) { - free(tab_prog_new[i]); - } + for (i = 0; i < args[1]; i++) { + free(tab_prog_new[i]); + } - free(tab_prog_new); - free(tab_length_new); + free(tab_prog_new); + free(tab_length_new); - free(tab_prog); + free(tab_prog); - break; - } + break; + } case glVertexPointer_fake_func: { @@ -2649,9 +2928,9 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, - (void *) args[5], bytes_size); + (void *)args[5], bytes_size); /* DEBUGF( "glVertexPointer_fake_func size=%d, type=%d, * stride=%d, byte_size=%d\n", size, type, stride, bytes_size); */ glVertexPointer(size, type, stride, @@ -2671,9 +2950,9 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->normalPointer = g_realloc(process->current_state->normalPointer, - process->current_state->normalPointerSize); + process->current_state->normalPointerSize); memcpy(process->current_state->normalPointer + offset, - (void *) args[4], bytes_size); + (void *)args[4], bytes_size); // DEBUGF( "glNormalPointer_fake_func type=%d, stride=%d, // byte_size=%d\n", type, stride, bytes_size); glNormalPointer(type, stride, @@ -2693,13 +2972,12 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->indexPointer = g_realloc(process->current_state->indexPointer, - process->current_state->indexPointerSize); + process->current_state->indexPointerSize); memcpy(process->current_state->indexPointer + offset, - (void *) args[4], bytes_size); + (void *)args[4], bytes_size); // DEBUGF( "glIndexPointer_fake_func type=%d, stride=%d, // byte_size=%d\n", type, stride, bytes_size); - glIndexPointer(type, stride, - process->current_state->indexPointer); + glIndexPointer(type, stride, process->current_state->indexPointer); break; } @@ -2714,13 +2992,12 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->edgeFlagPointer = g_realloc(process->current_state->edgeFlagPointer, - process->current_state->edgeFlagPointerSize); + process->current_state->edgeFlagPointerSize); memcpy(process->current_state->edgeFlagPointer + offset, - (void *) args[3], bytes_size); + (void *)args[3], bytes_size); // DEBUGF( "glEdgeFlagPointer_fake_func stride = %d, // bytes_size=%d\n", stride, bytes_size); - glEdgeFlagPointer(stride, - process->current_state->edgeFlagPointer); + glEdgeFlagPointer(stride, process->current_state->edgeFlagPointer); break; } @@ -2741,14 +3018,15 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->vertexAttribPointer[index] = g_realloc(process->current_state->vertexAttribPointer[index], - process->current_state-> - vertexAttribPointerSize[index]); - memcpy(process->current_state->vertexAttribPointer[index] + - offset, (void *) args[7], bytes_size); + process-> + current_state->vertexAttribPointerSize[index]); + memcpy(process->current_state->vertexAttribPointer[index] + offset, + (void *)args[7], bytes_size); ptr_func_glVertexAttribPointerARB(index, size, type, normalized, stride, - process->current_state-> - vertexAttribPointer[index]); + process-> + current_state->vertexAttribPointer + [index]); break; } @@ -2768,13 +3046,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->vertexAttribPointerNV[index] = g_realloc(process->current_state->vertexAttribPointerNV[index], - process->current_state-> - vertexAttribPointerNVSize[index]); + process-> + current_state->vertexAttribPointerNVSize[index]); memcpy(process->current_state->vertexAttribPointerNV[index] + - offset, (void *) args[6], bytes_size); + offset, (void *)args[6], bytes_size); ptr_func_glVertexAttribPointerNV(index, size, type, stride, - process->current_state-> - vertexAttribPointerNV[index]); + process-> + current_state->vertexAttribPointerNV + [index]); break; } @@ -2791,9 +3070,9 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->colorPointer = g_realloc(process->current_state->colorPointer, - process->current_state->colorPointerSize); + process->current_state->colorPointerSize); memcpy(process->current_state->colorPointer + offset, - (void *) args[5], bytes_size); + (void *)args[5], bytes_size); // DEBUGF( "glColorPointer_fake_func bytes_size = %d\n", // bytes_size); glColorPointer(size, type, stride, @@ -2804,8 +3083,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glSecondaryColorPointer_fake_func: { - GET_EXT_PTR(void, glSecondaryColorPointer, - (int, int, int, void *)); + GET_EXT_PTR(void, glSecondaryColorPointer, (int, int, int, void *)); int offset = args[0]; int size = args[1]; int type = args[2]; @@ -2817,14 +3095,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->secondaryColorPointer = g_realloc(process->current_state->secondaryColorPointer, - process->current_state->secondaryColorPointerSize); + process->current_state->secondaryColorPointerSize); memcpy(process->current_state->secondaryColorPointer + offset, - (void *) args[5], bytes_size); + (void *)args[5], bytes_size); // DEBUGF( "glSecondaryColorPointer_fake_func bytes_size // = %d\n", bytes_size); ptr_func_glSecondaryColorPointer(size, type, stride, - process->current_state-> - secondaryColorPointer); + process-> + current_state->secondaryColorPointer); break; } @@ -2835,16 +3113,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args if (process->current_state->clientStateSp < MAX_CLIENT_STATE_STACK_SIZE) { - process->current_state->clientStateStack[process-> - current_state-> - clientStateSp].mask = - mask; + process->current_state-> + clientStateStack[process->current_state->clientStateSp]. + mask = mask; if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { - process->current_state->clientStateStack[process-> - current_state-> - clientStateSp]. - activeTextureIndex = - process->current_state->activeTextureIndex; + process->current_state-> + clientStateStack + [process->current_state->clientStateSp].activeTextureIndex + = process->current_state->activeTextureIndex; } process->current_state->clientStateSp++; } @@ -2856,14 +3132,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args { if (process->current_state->clientStateSp > 0) { process->current_state->clientStateSp--; - if (process->current_state-> - clientStateStack[process->current_state->clientStateSp]. - mask & GL_CLIENT_VERTEX_ARRAY_BIT) { + if (process-> + current_state->clientStateStack[process->current_state-> + clientStateSp].mask & + GL_CLIENT_VERTEX_ARRAY_BIT) { process->current_state->activeTextureIndex = - process->current_state->clientStateStack[process-> - current_state-> - clientStateSp]. - activeTextureIndex; + process->current_state-> + clientStateStack + [process->current_state->clientStateSp].activeTextureIndex; } } glPopClientAttrib(); @@ -2895,17 +3171,17 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->texCoordPointer[index] = g_realloc(process->current_state->texCoordPointer[index], - process->current_state->texCoordPointerSize[index]); + process->current_state->texCoordPointerSize[index]); memcpy(process->current_state->texCoordPointer[index] + offset, - (void *) args[6], bytes_size); + (void *)args[6], bytes_size); /* DEBUGF( "glTexCoordPointer_fake_func size=%d, type=%d, * stride=%d, byte_size=%d\n", size, type, stride, bytes_size); */ do_glClientActiveTextureARB(GL_TEXTURE0_ARB + index); glTexCoordPointer(size, type, stride, process->current_state->texCoordPointer[index]); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -2923,22 +3199,20 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->weightPointer = g_realloc(process->current_state->weightPointer, - process->current_state->weightPointerSize); + process->current_state->weightPointerSize); memcpy(process->current_state->weightPointer + offset, - (void *) args[5], bytes_size); + (void *)args[5], bytes_size); /* DEBUGF( "glWeightPointerARB_fake_func size=%d, * type=%d, stride=%d, byte_size=%d\n", size, type, stride, * bytes_size); */ ptr_func_glWeightPointerARB(size, type, stride, - process->current_state-> - weightPointer); + process->current_state->weightPointer); break; } case glMatrixIndexPointerARB_fake_func: { - GET_EXT_PTR(void, glMatrixIndexPointerARB, - (int, int, int, void *)); + GET_EXT_PTR(void, glMatrixIndexPointerARB, (int, int, int, void *)); int offset = args[0]; int size = args[1]; int type = args[2]; @@ -2950,15 +3224,15 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->matrixIndexPointer = g_realloc(process->current_state->matrixIndexPointer, - process->current_state->matrixIndexPointerSize); + process->current_state->matrixIndexPointerSize); memcpy(process->current_state->matrixIndexPointer + offset, - (void *) args[5], bytes_size); + (void *)args[5], bytes_size); /* DEBUGF( "glMatrixIndexPointerARB_fake_func size=%d, * type=%d, stride=%d, byte_size=%d\n", size, type, stride, * bytes_size); */ ptr_func_glMatrixIndexPointerARB(size, type, stride, - process->current_state-> - matrixIndexPointer); + process-> + current_state->matrixIndexPointer); break; } @@ -2975,14 +3249,13 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->fogCoordPointer = g_realloc(process->current_state->fogCoordPointer, - process->current_state->fogCoordPointerSize); + process->current_state->fogCoordPointerSize); memcpy(process->current_state->fogCoordPointer + offset, - (void *) args[4], bytes_size); + (void *)args[4], bytes_size); // DEBUGF( "glFogCoordPointer_fake_func type=%d, // stride=%d, byte_size=%d\n", type, stride, bytes_size); ptr_func_glFogCoordPointer(type, stride, - process->current_state-> - fogCoordPointer); + process->current_state->fogCoordPointer); break; } @@ -3000,14 +3273,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->variantPointerEXT[id] = g_realloc(process->current_state->variantPointerEXT[id], - process->current_state->variantPointerEXTSize[id]); + process->current_state->variantPointerEXTSize[id]); memcpy(process->current_state->variantPointerEXT[id] + offset, - (void *) args[5], bytes_size); + (void *)args[5], bytes_size); // DEBUGF( "glVariantPointerEXT_fake_func[%d] type=%d, // stride=%d, byte_size=%d\n", id, type, stride, bytes_size); ptr_func_glVariantPointerEXT(id, type, stride, - process->current_state-> - variantPointerEXT[id]); + process-> + current_state->variantPointerEXT[id]); break; } @@ -3024,14 +3297,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args offset + bytes_size); process->current_state->interleavedArrays = g_realloc(process->current_state->interleavedArrays, - process->current_state->interleavedArraysSize); + process->current_state->interleavedArraysSize); memcpy(process->current_state->interleavedArrays + offset, - (void *) args[4], bytes_size); + (void *)args[4], bytes_size); // DEBUGF( "glInterleavedArrays_fake_func format=%d, // stride=%d, byte_size=%d\n", format, stride, bytes_size); ptr_func_glInterleavedArrays(format, stride, - process->current_state-> - interleavedArrays); + process-> + current_state->interleavedArrays); break; } @@ -3044,14 +3317,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->elementPointerATISize = bytes_size; process->current_state->elementPointerATI = g_realloc(process->current_state->elementPointerATI, - process->current_state->elementPointerATISize); + process->current_state->elementPointerATISize); memcpy(process->current_state->elementPointerATI, - (void *) args[2], bytes_size); + (void *)args[2], bytes_size); // DEBUGF( "glElementPointerATI_fake_func type=%d, // byte_size=%d\n", type, bytes_size); ptr_func_glElementPointerATI(type, - process->current_state-> - elementPointerATI); + process-> + current_state->elementPointerATI); break; } @@ -3065,9 +3338,9 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->texCoordPointerSize[0] = bytes_size; process->current_state->texCoordPointer[0] = g_realloc(process->current_state->texCoordPointer[0], - bytes_size); + bytes_size); memcpy(process->current_state->texCoordPointer[0], - (void *) args[4], bytes_size); + (void *)args[4], bytes_size); /* DEBUGF( "glTexCoordPointer01_fake_func size=%d, * type=%d, stride=%d, byte_size=%d\n", size, type, stride, * bytes_size); */ @@ -3078,8 +3351,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args glTexCoordPointer(size, type, stride, process->current_state->texCoordPointer[0]); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -3093,9 +3366,9 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->texCoordPointerSize[0] = bytes_size; process->current_state->texCoordPointer[0] = g_realloc(process->current_state->texCoordPointer[0], - bytes_size); + bytes_size); memcpy(process->current_state->texCoordPointer[0], - (void *) args[4], bytes_size); + (void *)args[4], bytes_size); /* DEBUGF( "glTexCoordPointer012_fake_func size=%d, * type=%d, stride=%d, byte_size=%d\n", size, type, stride, * bytes_size); */ @@ -3109,8 +3382,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args glTexCoordPointer(size, type, stride, process->current_state->texCoordPointer[0]); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -3122,7 +3395,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int normalPointerType = args[3]; int normalPointerStride = args[4]; int bytes_size = args[5]; - void *ptr = (void *) args[6]; + void *ptr = (void *)args[6]; process->current_state->vertexPointerSize = bytes_size; process->current_state->vertexPointer = @@ -3146,14 +3419,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int normalPointerOffset = args[i++]; int normalPointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3169,7 +3442,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int mode = args[0]; int count = args[1]; int isColorEnabled = args[2]; - void *ptr = (void *) args[3]; + void *ptr = (void *)args[3]; int stride = 6 * sizeof(float) + ((isColorEnabled) ? 4 * sizeof(unsigned char) : 0); @@ -3180,13 +3453,13 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args ptr + 6 * sizeof(float)); glDrawArrays(mode, 0, count); -#ifdef __APPLE__ //only for mac - { - int prev_fbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); - if ( prev_fbo != 0 ) - glFlush(); - } +#ifdef __APPLE__ //only for mac + { + int prev_fbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); + if (prev_fbo != 0) + glFlush(); + } #endif break; @@ -3205,14 +3478,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int colorPointerSize = args[i++]; int colorPointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3240,14 +3513,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int texCoord0PointerSize = args[i++]; int texCoord0PointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3261,8 +3534,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->vertexPointer + texCoord0PointerOffset); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -3279,14 +3552,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int texCoord0PointerSize = args[i++]; int texCoord0PointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3300,8 +3573,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->vertexPointer + texCoord0PointerOffset); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -3321,14 +3594,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int texCoord1PointerSize = args[i++]; int texCoord1PointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3347,8 +3620,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->vertexPointer + texCoord1PointerOffset); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -3371,14 +3644,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int texCoord2PointerSize = args[i++]; int texCoord2PointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3402,8 +3675,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->vertexPointer + texCoord2PointerOffset); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -3423,14 +3696,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int texCoord0PointerSize = args[i++]; int texCoord0PointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3447,8 +3720,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->vertexPointer + texCoord0PointerOffset); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -3471,14 +3744,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int texCoord1PointerSize = args[i++]; int texCoord1PointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3500,8 +3773,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->vertexPointer + texCoord1PointerOffset); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } @@ -3527,14 +3800,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args int texCoord2PointerSize = args[i++]; int texCoord2PointerType = args[i++]; int bytes_size = args[i++]; - void *ptr = (void *) args[i++]; + void *ptr = (void *)args[i++]; process->current_state->vertexPointerSize = MAX(process->current_state->vertexPointerSize, offset + bytes_size); process->current_state->vertexPointer = g_realloc(process->current_state->vertexPointer, - process->current_state->vertexPointerSize); + process->current_state->vertexPointerSize); memcpy(process->current_state->vertexPointer + offset, ptr, bytes_size); glVertexPointer(vertexPointerSize, vertexPointerType, stride, @@ -3561,53 +3834,52 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->vertexPointer + texCoord2PointerOffset); do_glClientActiveTextureARB(GL_TEXTURE0_ARB + - process->current_state-> - activeTextureIndex); + process-> + current_state->activeTextureIndex); break; } case _glVertexPointer_buffer_func: { - glVertexPointer(args[0], args[1], args[2], (void *) args[3]); + glVertexPointer(args[0], args[1], args[2], (void *)args[3]); break; } case _glNormalPointer_buffer_func: { - glNormalPointer(args[0], args[1], (void *) args[2]); + glNormalPointer(args[0], args[1], (void *)args[2]); break; } case _glColorPointer_buffer_func: { - glColorPointer(args[0], args[1], args[2], (void *) args[3]); + glColorPointer(args[0], args[1], args[2], (void *)args[3]); break; } case _glSecondaryColorPointer_buffer_func: { - GET_EXT_PTR(void, glSecondaryColorPointer, - (int, int, int, void *)); + GET_EXT_PTR(void, glSecondaryColorPointer, (int, int, int, void *)); ptr_func_glSecondaryColorPointer(args[0], args[1], args[2], - (void *) args[3]); + (void *)args[3]); break; } case _glIndexPointer_buffer_func: { - glIndexPointer(args[0], args[1], (void *) args[2]); + glIndexPointer(args[0], args[1], (void *)args[2]); break; } case _glTexCoordPointer_buffer_func: { - glTexCoordPointer(args[0], args[1], args[2], (void *) args[3]); + glTexCoordPointer(args[0], args[1], args[2], (void *)args[3]); break; } case _glEdgeFlagPointer_buffer_func: { - glEdgeFlagPointer(args[0], (void *) args[1]); + glEdgeFlagPointer(args[0], (void *)args[1]); break; } @@ -3617,7 +3889,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args (int, int, int, int, int, void *)); ptr_func_glVertexAttribPointerARB(args[0], args[1], args[2], args[3], args[4], - (void *) args[5]); + (void *)args[5]); break; } @@ -3626,16 +3898,15 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args GET_EXT_PTR(void, glWeightPointerARB, (int, int, int, void *)); ptr_func_glWeightPointerARB(args[0], args[1], args[2], - (void *) args[3]); + (void *)args[3]); break; } case _glMatrixIndexPointerARB_buffer_func: { - GET_EXT_PTR(void, glMatrixIndexPointerARB, - (int, int, int, void *)); + GET_EXT_PTR(void, glMatrixIndexPointerARB, (int, int, int, void *)); ptr_func_glMatrixIndexPointerARB(args[0], args[1], args[2], - (void *) args[3]); + (void *)args[3]); break; } @@ -3643,7 +3914,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args { GET_EXT_PTR(void, glFogCoordPointer, (int, int, void *)); - ptr_func_glFogCoordPointer(args[0], args[1], (void *) args[2]); + ptr_func_glFogCoordPointer(args[0], args[1], (void *)args[2]); break; } @@ -3652,21 +3923,21 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args GET_EXT_PTR(void, glVariantPointerEXT, (int, int, int, void *)); ptr_func_glVariantPointerEXT(args[0], args[1], args[2], - (void *) args[3]); + (void *)args[3]); break; } case _glDrawElements_buffer_func: { - glDrawElements(args[0], args[1], args[2], (void *) args[3]); + glDrawElements(args[0], args[1], args[2], (void *)args[3]); -#ifdef __APPLE__ //only for mac - { - int prev_fbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); - if ( prev_fbo != 0 ) - glFlush(); - } +#ifdef __APPLE__ //only for mac + { + int prev_fbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); + if (prev_fbo != 0) + glFlush(); + } #endif break; @@ -3675,7 +3946,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case _glDrawRangeElements_buffer_func: { glDrawRangeElements(args[0], args[1], args[2], args[3], args[4], - (void *) args[5]); + (void *)args[5]); break; } #endif @@ -3683,38 +3954,41 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args { GET_EXT_PTR(void, glMultiDrawElements, (int, int *, int, void **, int)); - ptr_func_glMultiDrawElements(args[0], (int *) args[1], args[2], - (void **) args[3], args[4]); -#ifdef __APPLE__ //only for mac - { - int prev_fbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); - if ( prev_fbo != 0 ) - glFlush(); - } + ptr_func_glMultiDrawElements(args[0], (int *)args[1], args[2], + (void **)args[3], args[4]); +#ifdef __APPLE__ //only for mac + { + int prev_fbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); + if (prev_fbo != 0) + glFlush(); + } #endif - break; - } -#ifdef __APPLE__ // only for mac - case glDrawArrays_func: - { - int prev_fbo; - glDrawArrays(ARG_TO_UNSIGNED_INT(args[0]), ARG_TO_INT(args[1]), ARG_TO_INT(args[2])); - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); - if ( prev_fbo != 0 ) - glFlush(); - break; - } - case glDrawElements_func: - { - int prev_fbo; - glDrawElements(ARG_TO_UNSIGNED_INT(args[0]), ARG_TO_INT(args[1]), ARG_TO_UNSIGNED_INT(args[2]), (const void*)(args[3])); - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); - if ( prev_fbo != 0 ) - glFlush(); - break; - } + break; + } +#ifdef __APPLE__ // only for mac + case glDrawArrays_func: + { + int prev_fbo; + glDrawArrays(ARG_TO_UNSIGNED_INT(args[0]), ARG_TO_INT(args[1]), + ARG_TO_INT(args[2])); + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); + if (prev_fbo != 0) + glFlush(); + break; + } + case glDrawElements_func: + { + int prev_fbo; + glDrawElements(ARG_TO_UNSIGNED_INT(args[0]), ARG_TO_INT(args[1]), + ARG_TO_UNSIGNED_INT(args[2]), + (const void *)(args[3])); + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &prev_fbo); + if (prev_fbo != 0) + glFlush(); + break; + } #endif case _glGetError_fake_func: @@ -3724,7 +3998,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args case glGetIntegerv_func: { - glGetIntegerv(args[0], (int *) args[1]); + glGetIntegerv(args[0], (int *)args[1]); break; } @@ -3733,7 +4007,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args glReadPixels(ARG_TO_INT(args[0]), ARG_TO_INT(args[1]), ARG_TO_INT(args[2]), ARG_TO_INT(args[3]), ARG_TO_UNSIGNED_INT(args[4]), - ARG_TO_UNSIGNED_INT(args[5]), (void *) (args[6])); + ARG_TO_UNSIGNED_INT(args[5]), (void *)(args[6])); break; } @@ -3741,8 +4015,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args { glDrawPixels(ARG_TO_INT(args[0]), ARG_TO_INT(args[1]), ARG_TO_UNSIGNED_INT(args[2]), - ARG_TO_UNSIGNED_INT(args[3]), - (const void *) (args[4])); + ARG_TO_UNSIGNED_INT(args[3]), (const void *)(args[4])); break; } @@ -3752,7 +4025,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args GET_EXT_PTR(GLboolean, glUnmapBufferARB, (GLenum)); int target = args[0]; int size = args[1]; - void *dst_ptr = (void *) args[2]; + void *dst_ptr = (void *)args[2]; void *src_ptr = ptr_func_glMapBufferARB(target, GL_READ_ONLY); if (src_ptr) { @@ -3769,7 +4042,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args GET_GLU_PTR(GLint, gluBuild2DMipmaps, (GLenum arg_0, GLint arg_1, GLsizei arg_2, GLsizei arg_3, GLenum arg_4, GLenum arg_5, - const GLvoid *arg_6)); + const GLvoid * arg_6)); if (ptr_func_gluBuild2DMipmaps == NULL) ptr_func_gluBuild2DMipmaps = mesa_gluBuild2DMipmaps; ptr_func_gluBuild2DMipmaps(ARG_TO_UNSIGNED_INT(args[0]), @@ -3778,7 +4051,7 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args ARG_TO_INT(args[3]), ARG_TO_UNSIGNED_INT(args[4]), ARG_TO_UNSIGNED_INT(args[5]), - (const void *) (args[6])); + (const void *)(args[6])); break; } @@ -3787,14 +4060,14 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->selectBufferSize = args[0] * 4; process->current_state->selectBufferPtr = g_realloc(process->current_state->selectBufferPtr, - process->current_state->selectBufferSize); + process->current_state->selectBufferSize); glSelectBuffer(args[0], process->current_state->selectBufferPtr); break; } case _glGetSelectBuffer_fake_func: { - void *ptr = (void *) args[0]; + void *ptr = (void *)args[0]; memcpy(ptr, process->current_state->selectBufferPtr, process->current_state->selectBufferSize); @@ -3806,15 +4079,15 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args process->current_state->feedbackBufferSize = args[0] * 4; process->current_state->feedbackBufferPtr = g_realloc(process->current_state->feedbackBufferPtr, - process->current_state->feedbackBufferSize); - glFeedbackBuffer((GLsizei)args[0], (GLenum) args[1], + process->current_state->feedbackBufferSize); + glFeedbackBuffer((GLsizei) args[0], (GLenum) args[1], process->current_state->feedbackBufferPtr); break; } case _glGetFeedbackBuffer_fake_func: { - void *ptr = (void *) args[0]; + void *ptr = (void *)args[0]; memcpy(ptr, process->current_state->feedbackBufferPtr, process->current_state->feedbackBufferSize); @@ -3866,12 +4139,12 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args GET_EXT_PTR(int, glNewObjectBufferATI, (int, void *, int)); ret.i = ptr_func_glNewObjectBufferATI(args[0], - (void *) args[1], args[2]); + (void *)args[1], args[2]); break; } case glClear_func: - glClear((GLbitfield)args[0]); + glClear((GLbitfield) args[0]); break; #if 0 /* HACK workaround for an unexplainable issue */ @@ -3887,65 +4160,68 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args #endif #ifdef _WIN32 - /* workaround for bug T_SDK-128. If GL_UNPACK_ROW_LENGTH==0, GL driver - * should calculate it for glTexSubImage2D according to width parameter and - * GL_UNPACK_ALIGNMENT. But on windows, some vender's driver like nvidia, - * don't follow it. So we need do it for the driver, and probably remove - * this hack in future if driver get fixed. - */ - case glTexSubImage2D_func: - { - int origin_row_length, alignment, width; - - if (args[6] == GL_ALPHA) { - width = args[4]; - glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); - glGetIntegerv(GL_UNPACK_ROW_LENGTH, &origin_row_length); - - if (width%alignment != 0) { - width = (width/alignment + 1) * alignment; - } - - glPixelStorei(GL_UNPACK_ROW_LENGTH, width); - } - - glTexSubImage2D(ARG_TO_UNSIGNED_INT(args[0]), ARG_TO_INT(args[1]), - ARG_TO_INT(args[2]), ARG_TO_INT(args[3]), - ARG_TO_INT(args[4]), ARG_TO_INT(args[5]), - ARG_TO_UNSIGNED_INT(args[6]), - ARG_TO_UNSIGNED_INT(args[7]), (const void*)(args[8])); - - if (args[6] == GL_ALPHA) - glPixelStorei(GL_UNPACK_ROW_LENGTH, origin_row_length); - - break; - } + /* workaround for bug T_SDK-128. If GL_UNPACK_ROW_LENGTH==0, GL driver + * should calculate it for glTexSubImage2D according to width parameter and + * GL_UNPACK_ALIGNMENT. But on windows, some vender's driver like nvidia, + * don't follow it. So we need do it for the driver, and probably remove + * this hack in future if driver get fixed. + */ + case glTexSubImage2D_func: + { + int origin_row_length, alignment, width; + + if (args[6] == GL_ALPHA) { + width = args[4]; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &origin_row_length); + + if (width % alignment != 0) { + width = (width / alignment + 1) * alignment; + } + + glPixelStorei(GL_UNPACK_ROW_LENGTH, width); + } + + glTexSubImage2D(ARG_TO_UNSIGNED_INT(args[0]), ARG_TO_INT(args[1]), + ARG_TO_INT(args[2]), ARG_TO_INT(args[3]), + ARG_TO_INT(args[4]), ARG_TO_INT(args[5]), + ARG_TO_UNSIGNED_INT(args[6]), + ARG_TO_UNSIGNED_INT(args[7]), + (const void *)(args[8])); + + if (args[6] == GL_ALPHA) + glPixelStorei(GL_UNPACK_ROW_LENGTH, origin_row_length); + + break; + } #endif #ifdef __APPLE__ - case glTexSubImage2D_func: - { - - glTexSubImage2D(ARG_TO_UNSIGNED_INT(args[0]), ARG_TO_INT(args[1]), - ARG_TO_INT(args[2]), ARG_TO_INT(args[3]), - ARG_TO_INT(args[4]), ARG_TO_INT(args[5]), - ARG_TO_UNSIGNED_INT(args[6]), ARG_TO_UNSIGNED_INT(args[7]), - (const void*)(args[8])); - - if ( ARG_TO_UNSIGNED_INT(args[0]) == GL_TEXTURE_2D && - ARG_TO_INT(args[1]) == 0 && - ARG_TO_UNSIGNED_INT(args[6]) == GL_RGBA && - ARG_TO_UNSIGNED_INT(args[7]) == GL_UNSIGNED_BYTE ) - mac_dump_texture(); - else - fprintf(stderr, "!!! Probable screen crash, no work around as glTexSubImage2d parameters do not match!\n"); - - break; - } + case glTexSubImage2D_func: + { + + glTexSubImage2D(ARG_TO_UNSIGNED_INT(args[0]), ARG_TO_INT(args[1]), + ARG_TO_INT(args[2]), ARG_TO_INT(args[3]), + ARG_TO_INT(args[4]), ARG_TO_INT(args[5]), + ARG_TO_UNSIGNED_INT(args[6]), + ARG_TO_UNSIGNED_INT(args[7]), + (const void *)(args[8])); + + if (ARG_TO_UNSIGNED_INT(args[0]) == GL_TEXTURE_2D && + ARG_TO_INT(args[1]) == 0 && + ARG_TO_UNSIGNED_INT(args[6]) == GL_RGBA && + ARG_TO_UNSIGNED_INT(args[7]) == GL_UNSIGNED_BYTE) + mac_dump_texture(); + else + fprintf(stderr, + "!!! Probable screen crash, no work around as glTexSubImage2d parameters do not match!\n"); + + break; + } #endif default: - execute_func(func_number, (void**)args, &ret); + execute_func(func_number, (void **)args, &ret); break; } @@ -3964,14 +4240,29 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args } default: - DEBUGF( "unexpected ret type : %d\n", ret_type); + DEBUGF("unexpected ret type : %d\n", ret_type); exit(-1); break; } + if (TRACE_ON(qemu)) { + gettimeofday(&t1, NULL); + qemu_timersub(&t1, &t0, &t1); + unsigned long duration = t1.tv_sec * 1000000 + t1.tv_usec; + struct GLCallStatInfo *stats = &(process->stats[func_number]); + stats->n++; + stats->total += duration; + if (duration > stats->max) + stats->max = duration; + if (stats->total > 0) + TRACE("[%d]< %s (n %llu, total %llu, max %llu, moy %llu)\n", + process->p.process_id, tab_opengl_calls_name[func_number], + stats->n, stats->total, stats->max, stats->total / stats->n); + } + if (display_function_call) - DEBUGF( "[%d]< %s\n", process->p.process_id, - tab_opengl_calls_name[func_number]); + DEBUGF("[%d]< %s\n", process->p.process_id, + tab_opengl_calls_name[func_number]); return ret.i; } diff --git a/tizen/src/hw/opengl_exec.h b/tizen/src/hw/opengl_exec.h index 9bd828b084..a801ae7f94 100644 --- a/tizen/src/hw/opengl_exec.h +++ b/tizen/src/hw/opengl_exec.h @@ -24,11 +24,10 @@ * THE SOFTWARE. */ - #include -extern void gl_disconnect(ProcessStruct *process); +extern void gl_disconnect(ProcessStruct * process); extern ProcessStruct *vmgl_get_process(pid_t pid); -extern void vmgl_context_switch(ProcessStruct *process, int switch_gl_context); -extern int do_function_call(ProcessStruct *process, int func_number, +extern void vmgl_context_switch(ProcessStruct * process, int switch_gl_context); +extern int do_function_call(ProcessStruct * process, int func_number, unsigned long *args, char *ret_string); diff --git a/tizen/src/hw/opengl_func.h b/tizen/src/hw/opengl_func.h index e29f0d901f..942c614891 100644 --- a/tizen/src/hw/opengl_func.h +++ b/tizen/src/hw/opengl_func.h @@ -32,10 +32,8 @@ #ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64 -#define TARGET_PHYS_ADDR_BITS 64 #else #define TARGET_LONG_BITS 32 -#define TARGET_PHYS_ADDR_BITS 32 #endif //#define NEED_CPU_H @@ -219,7 +217,6 @@ enum { #define CASE_POINTERS CASE_IN_POINTERS: CASE_OUT_POINTERS #define CASE_KNOWN_SIZE_POINTERS CASE_IN_KNOWN_SIZE_POINTERS: CASE_OUT_KNOWN_SIZE_POINTERS - #define IS_ARRAY_CHAR(type) (type == TYPE_ARRAY_CHAR || type == TYPE_1CHAR || type == TYPE_2CHAR || type == TYPE_3CHAR || type == TYPE_4CHAR || type == TYPE_ARRAY_CHAR_OF_LENGTH_DEPENDING_ON_PREVIOUS_ARGS) #define IS_ARRAY_SHORT(type) (type == TYPE_ARRAY_SHORT || type == TYPE_1SHORT || type == TYPE_2SHORT || type == TYPE_3SHORT || type == TYPE_4SHORT || type == TYPE_ARRAY_SHORT_OF_LENGTH_DEPENDING_ON_PREVIOUS_ARGS) #define IS_ARRAY_INT(type) (type == TYPE_ARRAY_INT || type == TYPE_1INT || type == TYPE_2INT || type == TYPE_3INT || type == TYPE_4INT || type == TYPE_ARRAY_INT_OF_LENGTH_DEPENDING_ON_PREVIOUS_ARGS) @@ -244,10 +241,10 @@ static const int _init64_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_1INT }; static const int _resize_surface_signature[] = - {TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_INT}; + { TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_INT }; static const int _render_surface_signature[] = - {TYPE_NONE, 1, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_OUT_ARRAY_CHAR}; + { TYPE_NONE, 1, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_OUT_ARRAY_CHAR }; /* XVisualInfo* glXChooseVisual( Display *dpy, int screen, int *attribList ) */ static const int glXChooseVisual_signature[] = @@ -260,7 +257,8 @@ static const int glXCreateContext_signature[] = static const int glXCopyContext_signature[] = { TYPE_NONE, 0, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_INT }; + TYPE_INT +}; /* void glXDestroyContext( Display *dpy, GLXContext ctx ) */ static const int glXDestroyContext_signature[] = @@ -275,12 +273,14 @@ static const int glXMakeCurrent_signature[] = int attrib, int *value )*/ static const int glXGetConfig_signature[] = { TYPE_INT, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_OUT_1INT }; + TYPE_OUT_1INT +}; /* "glXGetConfig_extended"(dpy, visual_id, int n, int* attribs, int* values, int* rets) */ static const int glXGetConfig_extended_signature[] = { TYPE_NONE, 1, 6, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_ARRAY_INT, TYPE_OUT_ARRAY_INT, TYPE_OUT_ARRAY_INT }; + TYPE_ARRAY_INT, TYPE_OUT_ARRAY_INT, TYPE_OUT_ARRAY_INT +}; /* void glXSwapBuffers( Display *dpy, GLXDrawable drawable ); */ static const int glXSwapBuffers_signature[] = @@ -311,14 +311,12 @@ static const int glXQueryExtensionsString_signature[] = static const int glXQueryServerString_signature[] = { TYPE_CONST_CHAR, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT }; - static const int glXGetProcAddress_fake_signature[] = { TYPE_INT, 0, 1, TYPE_NULL_TERMINATED_STRING }; static const int glXGetProcAddress_global_fake_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_ARRAY_CHAR, TYPE_OUT_ARRAY_CHAR }; - /* GLX 1.3 and later */ /* @@ -326,11 +324,13 @@ GLXFBConfig *glXChooseFBConfig( Display *dpy, int screen, const int *attribList, int *nitems ); */ static const int glXChooseFBConfig_signature[] = { TYPE_INT, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_ARRAY_INT, -TYPE_OUT_1INT }; + TYPE_OUT_1INT +}; static const int glXChooseFBConfigSGIX_signature[] = { TYPE_INT, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_ARRAY_INT, -TYPE_OUT_1INT }; + TYPE_OUT_1INT +}; static const int glXGetFBConfigs_signature[] = { TYPE_INT, 1, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_OUT_1INT }; @@ -338,8 +338,8 @@ static const int glXGetFBConfigs_signature[] = /* "glXGetFBConfigAttrib_extended"(dpy, fbconfig, int n, int* attribs, int* values, int* rets) */ static const int glXGetFBConfigAttrib_extended_signature[] = { TYPE_NONE, 1, 6, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_ARRAY_INT, TYPE_OUT_ARRAY_INT, TYPE_OUT_ARRAY_INT }; - + TYPE_ARRAY_INT, TYPE_OUT_ARRAY_INT, TYPE_OUT_ARRAY_INT +}; /* GLXPbuffer glXCreatePbuffer( Display *dpy, GLXFBConfig config, const int *attribList ) */ @@ -348,7 +348,8 @@ static const int glXCreatePbuffer_signature[] = static const int glXCreateGLXPbufferSGIX_signature[] = { TYPE_INT, 0, 5, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_INT }; + TYPE_ARRAY_INT +}; static const int glXDestroyPbuffer_signature[] = { TYPE_NONE, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT }; @@ -363,11 +364,13 @@ static const int glXDestroyGLXPbufferSGIX_signature[] = Bool Direct) */ static const int glXCreateNewContext_signature[] = { TYPE_INT, 0, 5, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT }; + TYPE_INT +}; static const int glXCreateContextWithConfigSGIX_signature[] = { TYPE_INT, 0, 5, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT }; + TYPE_INT +}; /*XVisualInfo *glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) */ static const int glXGetVisualFromFBConfig_signature[] = @@ -376,23 +379,28 @@ static const int glXGetVisualFromFBConfig_signature[] = /*int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value)*/ static const int glXGetFBConfigAttrib_signature[] = { TYPE_INT, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_OUT_1INT }; + TYPE_OUT_1INT +}; static const int glXGetFBConfigAttribSGIX_signature[] = { TYPE_INT, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_OUT_1INT }; + TYPE_OUT_1INT +}; static const int glXQueryContext_signature[] = { TYPE_INT, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_OUT_1INT }; + TYPE_OUT_1INT +}; static const int glXQueryGLXPbufferSGIX_signature[] = { TYPE_INT, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_OUT_1INT }; + TYPE_OUT_1INT +}; static const int glXQueryDrawable_signature[] = { TYPE_NONE, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, -TYPE_OUT_1INT }; + TYPE_OUT_1INT +}; /* void glXUseXFont( Font font, int first, int count, int list ) */ static const int glXUseXFont_signature[] = @@ -408,18 +416,17 @@ static const int glXGetScreenDriver_signature[] = static const int glXGetDriverConfig_signature[] = { TYPE_CONST_CHAR, 0, 1, TYPE_NULL_TERMINATED_STRING }; - static const int glXWaitVideoSyncSGI_signature[] = { TYPE_INT, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_1INT }; static const int glXGetVideoSyncSGI_signature[] = { TYPE_INT, 1, 1, TYPE_OUT_1INT }; -static const int glXSwapIntervalSGI_signature[] = - { TYPE_INT, 0, 1, TYPE_INT }; +static const int glXSwapIntervalSGI_signature[] = { TYPE_INT, 0, 1, TYPE_INT }; static const int glXCreatePixmap_signature[] = - { TYPE_INT, 0, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, TYPE_ARRAY_INT }; + { TYPE_INT, 0, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, +TYPE_ARRAY_INT }; static const int glXDestroyPixmap_signature[] = { TYPE_NONE, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT }; @@ -437,8 +444,7 @@ static const int glEGLImageTargetTexture2DOES_fake_signature[] = { TYPE_NONE, 0, 2, TYPE_UNSIGNED_INT, TYPE_INT }; /* const GLubyte * glGetString( GLenum name ) */ -static const int glGetString_signature[] = - { TYPE_CONST_CHAR, 0, 1, TYPE_INT }; +static const int glGetString_signature[] = { TYPE_CONST_CHAR, 0, 1, TYPE_INT }; /* void glShaderSourceARB (GLhandleARB handle , GLsizei size, const GLcharARB* *p_tab_prog, const GLint * tab_length) */ /* --> void glShaderSourceARB (GLhandleARB handle , GLsizei size, const GLcharARB* all_progs, const GLint * tab_length) */ @@ -449,94 +455,144 @@ static const int glShaderSource_fake_signature[] = static const int glVertexPointer_fake_signature[] = { TYPE_NONE, 0, 6, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glNormalPointer_fake_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glColorPointer_fake_signature[] = { TYPE_NONE, 0, 6, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glSecondaryColorPointer_fake_signature[] = { TYPE_NONE, 0, 6, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glIndexPointer_fake_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glTexCoordPointer_fake_signature[] = { TYPE_NONE, 0, 7, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_ARRAY_CHAR +}; static const int glEdgeFlagPointer_fake_signature[] = { TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; static const int glVertexAttribPointerARB_fake_signature[] = { TYPE_NONE, 0, 8, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int glVertexAttribPointerNV_fake_signature[] = { TYPE_NONE, 0, 7, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int glWeightPointerARB_fake_signature[] = { TYPE_NONE, 0, 6, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glMatrixIndexPointerARB_fake_signature[] = { TYPE_NONE, 0, 6, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glFogCoordPointer_fake_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glInterleavedArrays_fake_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; static const int glElementPointerATI_fake_signature[] = { TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; static const int glVariantPointerEXT_fake_signature[] = { TYPE_NONE, 0, 6, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; static const int glTuxRacerDrawElements_fake_signature[] = { TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; static const int glVertexAndNormalPointer_fake_signature[] = { TYPE_NONE, 0, 7, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int glTexCoordPointer01_fake_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glTexCoordPointer012_fake_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_ARRAY_CHAR +}; + static const int glVertexNormalPointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 8, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int glVertexNormalColorPointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 11, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int glVertexColorTexCoord0PointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 12, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int glVertexNormalTexCoord0PointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 11, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int glVertexNormalTexCoord01PointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 14, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, + TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int glVertexNormalTexCoord012PointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 17, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int - glVertexNormalColorTexCoord0PointerInterlaced_fake_signature[] = + glVertexNormalColorTexCoord0PointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 14, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, + TYPE_INT, + TYPE_ARRAY_CHAR +}; + static const int - glVertexNormalColorTexCoord01PointerInterlaced_fake_signature[] = + glVertexNormalColorTexCoord01PointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 17, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, + TYPE_INT, + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR +}; + static const int - glVertexNormalColorTexCoord012PointerInterlaced_fake_signature[] = + glVertexNormalColorTexCoord012PointerInterlaced_fake_signature[] = { TYPE_NONE, 0, 20, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR }; + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, + TYPE_INT, + TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR +}; -static const int glGenTextures_fake_signature[] = - { TYPE_NONE, 0, 1, TYPE_INT }; +static const int glGenTextures_fake_signature[] = { TYPE_NONE, 0, 1, TYPE_INT }; static const int glGenBuffersARB_fake_signature[] = { TYPE_NONE, 0, 1, TYPE_INT }; static const int glGenLists_fake_signature[] = { TYPE_NONE, 0, 1, TYPE_INT }; @@ -545,10 +601,13 @@ static const int _glDrawElements_buffer_signature[] = { TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT }; static const int _glDrawRangeElements_buffer_signature[] = { TYPE_NONE, 0, 6, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT }; + TYPE_INT +}; + static const int _glMultiDrawElements_buffer_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_ARRAY_INT, TYPE_INT, TYPE_ARRAY_INT, -TYPE_INT }; + TYPE_INT +}; static const int _glVertexPointer_buffer_signature[] = { TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT }; @@ -566,7 +625,8 @@ static const int _glEdgeFlagPointer_buffer_signature[] = { TYPE_NONE, 0, 2, TYPE_INT, TYPE_INT }; static const int _glVertexAttribPointerARB_buffer_signature[] = { TYPE_NONE, 0, 6, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT }; + TYPE_INT +}; static const int _glWeightPointerARB_buffer_signature[] = { TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT }; static const int _glMatrixIndexPointerARB_buffer_signature[] = @@ -578,7 +638,8 @@ static const int _glVariantPointerEXT_buffer_signature[] = static const int _glReadPixels_pbo_signature[] = { TYPE_INT, 0, 7, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, -TYPE_INT, TYPE_INT }; + TYPE_INT, TYPE_INT +}; static const int _glDrawPixels_pbo_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT }; static const int _glMapBufferARB_fake_signature[] = @@ -605,5 +666,4 @@ static const int _glGetError_fake_signature[] = { TYPE_NONE, 0, 0 }; func_number == glBufferDataARB_func || \ func_number == glNewObjectBufferATI_func) -#endif // INCLUDE_OPENGL_FUNC_H - +#endif // INCLUDE_OPENGL_FUNC_H diff --git a/tizen/src/hw/opengl_process.h b/tizen/src/hw/opengl_process.h index 5a923878fe..ba518ebf71 100644 --- a/tizen/src/hw/opengl_process.h +++ b/tizen/src/hw/opengl_process.h @@ -22,12 +22,16 @@ * THE SOFTWARE. */ +#ifndef __OPENGL_PROCESS_H +#define __OPENGL_PROCESS_H + typedef struct { int process_id; int wordsize; int rq_l, rrq_l; - int sum; // Debugging only + int sum; // Debugging only char *rq, *rq_p; char *rrq, *rrq_p; } ProcessStruct; +#endif diff --git a/tizen/src/hw/parse_gl_h.c b/tizen/src/hw/parse_gl_h.c index ed250a0885..886442d79d 100644 --- a/tizen/src/hw/parse_gl_h.c +++ b/tizen/src/hw/parse_gl_h.c @@ -30,1119 +30,1076 @@ #define GL_INCLUDE_PATH "../tizen/src/hw/" - -int isExtByName(const char* name) +int isExtByName(const char *name) { - return (strstr(name, "ARB") != NULL) || - (strstr(name, "IBM") != NULL) || - (strstr(name, "EXT") != NULL) || - (strstr(name, "ATI") != NULL) || - (strstr(name, "NV") != NULL) || - (strstr(name, "MESA") != NULL) || - (strstr(name, "APPLE") != NULL) || - (strstr(name, "SUN") != NULL) || - (strstr(name, "SGI") != NULL); + return (strstr(name, "ARB") != NULL) || + (strstr(name, "IBM") != NULL) || + (strstr(name, "EXT") != NULL) || + (strstr(name, "ATI") != NULL) || + (strstr(name, "NV") != NULL) || + (strstr(name, "MESA") != NULL) || + (strstr(name, "APPLE") != NULL) || + (strstr(name, "SUN") != NULL) || (strstr(name, "SGI") != NULL); } -char* get_arg_type(char* s) +char *get_arg_type(char *s) { - while(*s == ' ' || *s == '\t') s++; - char* n = s; - char* c = strstr(n, "const"); - if (c) - n += 6; - - char* t = strstr(n, " "); - if (t) - { - if (t[1] == '*') - t += 2; - t[0] = 0; - char* ori = t; - t = strstr(t+1, "["); - if (t) - { - memmove(ori, t, strlen(t)); - strstr(ori, "]")[1] = 0; + while (*s == ' ' || *s == '\t') + s++; + char *n = s; + char *c = strstr(n, "const"); + if (c) + n += 6; + + char *t = strstr(n, " "); + if (t) { + if (t[1] == '*') + t += 2; + t[0] = 0; + char *ori = t; + t = strstr(t + 1, "["); + if (t) { + memmove(ori, t, strlen(t)); + strstr(ori, "]")[1] = 0; + } } - } - return strdup(s); + return strdup(s); } -typedef struct -{ - char* type; - char* name; - int nargs; - char** args; - int ok; - int just_for_server_side; - int has_out_parameters; - int isExt; +typedef struct { + char *type; + char *name; + int nargs; + char **args; + int ok; + int just_for_server_side; + int has_out_parameters; + int isExt; } FuncDesc; -int isExt(FuncDesc* func) +int isExt(FuncDesc * func) { - return func->isExt; + return func->isExt; } -char* get_type_string(char* type) +char *get_type_string(char *type) { - if (strstr(type, "[16]")) - { - if (strstr(type, "float")) - return ("TYPE_16FLOAT"); - else if (strstr(type, "double")) - return ("TYPE_16DOUBLE"); - else - { - printf("inconnu %s\n", type); - exit(-1); + if (strstr(type, "[16]")) { + if (strstr(type, "float")) + return ("TYPE_16FLOAT"); + else if (strstr(type, "double")) + return ("TYPE_16DOUBLE"); + else { + printf("inconnu %s\n", type); + exit(-1); + } + } else if (strstr(type, "[128]") && strstr(type, "GLubyte")) + return strstr(type, "const") ? "TYPE_128UCHAR" : "TYPE_OUT_128UCHAR"; + else if (strstr(type, "const GLvoid *")) + return "TYPE_ARRAY_VOID"; + else if (strstr(type, "const GLchar *") || + strstr(type, "const GLcharARB *")) + return "TYPE_NULL_TERMINATED_STRING"; + else if (strstr(type, "const GLbyte *")) + return "TYPE_ARRAY_SIGNED_CHAR"; + else if (strstr(type, "const GLubyte *")) + return "TYPE_ARRAY_UNSIGNED_CHAR"; + else if (strstr(type, "const GLshort *")) + return "TYPE_ARRAY_SHORT"; + else if (strstr(type, "const GLushort *") || + strstr(type, "const GLhalfNV *")) + return "TYPE_ARRAY_UNSIGNED_SHORT"; + else if (strstr(type, "const GLint *")) + return "TYPE_ARRAY_INT"; + else if (strstr(type, "const GLuint *") || strstr(type, "const GLenum *")) + return "TYPE_ARRAY_UNSIGNED_INT"; + else if (strstr(type, "const GLfloat *") || + strstr(type, "const GLclampf *")) + return "TYPE_ARRAY_FLOAT"; + else if (strstr(type, "const GLdouble *")) + return "TYPE_ARRAY_DOUBLE"; + else if (strstr(type, "GLvoid *")) + return "TYPE_OUT_ARRAY_VOID"; + else if (strstr(type, "GLboolean *") || strstr(type, "GLubyte *")) + return "TYPE_OUT_ARRAY_UNSIGNED_CHAR"; + else if (strstr(type, "GLcharARB *") || strstr(type, "GLchar *")) + return "TYPE_OUT_ARRAY_CHAR"; + else if (strstr(type, "GLshort *")) + return "TYPE_OUT_ARRAY_SHORT"; + else if (strstr(type, "GLushort *")) + return "TYPE_OUT_ARRAY_UNSIGNED_SHORT"; + else if (strstr(type, "GLint *") || strstr(type, "GLsizei *")) + return "TYPE_OUT_ARRAY_INT"; + else if (strstr(type, "GLuint *") || + strstr(type, "GLenum *") || strstr(type, "GLhandleARB *")) + return "TYPE_OUT_ARRAY_UNSIGNED_INT"; + else if (strstr(type, "GLfloat *")) + return "TYPE_OUT_ARRAY_FLOAT"; + else if (strstr(type, "GLdouble *")) + return "TYPE_OUT_ARRAY_DOUBLE"; + else if (strcmp(type, "void") == 0) + return ("TYPE_NONE"); + else if (strcmp(type, "GLbyte") == 0) + return ("TYPE_CHAR"); + else if (strcmp(type, "GLubyte") == 0 || strcmp(type, "GLboolean") == 0) + return ("TYPE_UNSIGNED_CHAR"); + else if (strcmp(type, "GLshort") == 0) + return ("TYPE_SHORT"); + else if (strcmp(type, "GLushort") == 0 || strcmp(type, "GLhalfNV") == 0) + return ("TYPE_UNSIGNED_SHORT"); + else if (strcmp(type, "GLint") == 0 || + strcmp(type, "GLsizei") == 0 || + strcmp(type, "GLintptr") == 0 || + strcmp(type, "GLsizeiptr") == 0 || + strcmp(type, "GLintptrARB") == 0 || + strcmp(type, "GLsizeiptrARB") == 0) + return ("TYPE_INT"); + else if (strcmp(type, "GLenum") == 0 || + strcmp(type, "GLuint") == 0 || + strcmp(type, "GLhandleARB") == 0 || + strcmp(type, "GLbitfield") == 0) + return ("TYPE_UNSIGNED_INT"); + else if (strcmp(type, "GLfloat") == 0 || strcmp(type, "GLclampf") == 0) + return ("TYPE_FLOAT"); + else if (strcmp(type, "GLdouble") == 0 || strcmp(type, "GLclampd") == 0) + return ("TYPE_DOUBLE"); + else { + printf("inconnu %s\n", type); + exit(-1); } - } - else if (strstr(type, "[128]") && strstr(type, "GLubyte")) - return strstr(type, "const") ? "TYPE_128UCHAR" : "TYPE_OUT_128UCHAR"; - else if (strstr(type, "const GLvoid *")) - return "TYPE_ARRAY_VOID"; - else if (strstr(type, "const GLchar *") || - strstr(type, "const GLcharARB *")) - return "TYPE_NULL_TERMINATED_STRING"; - else if (strstr(type, "const GLbyte *")) - return "TYPE_ARRAY_SIGNED_CHAR"; - else if (strstr(type, "const GLubyte *")) - return "TYPE_ARRAY_UNSIGNED_CHAR"; - else if (strstr(type, "const GLshort *")) - return "TYPE_ARRAY_SHORT"; - else if (strstr(type, "const GLushort *") || - strstr(type, "const GLhalfNV *")) - return "TYPE_ARRAY_UNSIGNED_SHORT"; - else if (strstr(type, "const GLint *")) - return "TYPE_ARRAY_INT"; - else if (strstr(type, "const GLuint *") || - strstr(type, "const GLenum *")) - return "TYPE_ARRAY_UNSIGNED_INT"; - else if (strstr(type, "const GLfloat *") || - strstr(type, "const GLclampf *")) - return "TYPE_ARRAY_FLOAT"; - else if (strstr(type, "const GLdouble *")) - return "TYPE_ARRAY_DOUBLE"; - else if (strstr(type, "GLvoid *")) - return "TYPE_OUT_ARRAY_VOID"; - else if (strstr(type, "GLboolean *") || - strstr(type, "GLubyte *")) - return "TYPE_OUT_ARRAY_UNSIGNED_CHAR"; - else if (strstr(type, "GLcharARB *") || - strstr(type, "GLchar *")) - return "TYPE_OUT_ARRAY_CHAR"; - else if (strstr(type, "GLshort *")) - return "TYPE_OUT_ARRAY_SHORT"; - else if (strstr(type, "GLushort *")) - return "TYPE_OUT_ARRAY_UNSIGNED_SHORT"; - else if (strstr(type, "GLint *")|| - strstr(type, "GLsizei *")) - return "TYPE_OUT_ARRAY_INT"; - else if (strstr(type, "GLuint *") || - strstr(type, "GLenum *") || - strstr(type, "GLhandleARB *")) - return "TYPE_OUT_ARRAY_UNSIGNED_INT"; - else if (strstr(type, "GLfloat *")) - return "TYPE_OUT_ARRAY_FLOAT"; - else if (strstr(type, "GLdouble *")) - return "TYPE_OUT_ARRAY_DOUBLE"; - else if (strcmp(type, "void") == 0) - return("TYPE_NONE"); - else if (strcmp(type, "GLbyte") == 0) - return("TYPE_CHAR"); - else if (strcmp(type, "GLubyte") == 0 || - strcmp(type, "GLboolean") == 0) - return("TYPE_UNSIGNED_CHAR"); - else if (strcmp(type, "GLshort") == 0) - return("TYPE_SHORT"); - else if (strcmp(type, "GLushort") == 0 || - strcmp(type, "GLhalfNV") == 0) - return("TYPE_UNSIGNED_SHORT"); - else if (strcmp(type, "GLint") == 0 || - strcmp(type, "GLsizei") == 0 || - strcmp(type, "GLintptr") == 0 || - strcmp(type, "GLsizeiptr") == 0 || - strcmp(type, "GLintptrARB") == 0 || - strcmp(type, "GLsizeiptrARB") == 0) - return("TYPE_INT"); - else if (strcmp(type, "GLenum") == 0 || - strcmp(type, "GLuint") == 0 || - strcmp(type, "GLhandleARB") == 0 || - strcmp(type, "GLbitfield") == 0) - return("TYPE_UNSIGNED_INT"); - else if (strcmp(type, "GLfloat") == 0 || - strcmp(type, "GLclampf") == 0) - return("TYPE_FLOAT"); - else if (strcmp(type, "GLdouble") == 0 || - strcmp(type, "GLclampd") == 0) - return("TYPE_DOUBLE"); - else - { - printf("inconnu %s\n", type); - exit(-1); - } } -typedef struct -{ - char* letter; - char* signature_type_name; - char* gl_c_type_name; - char* c_type_name; +typedef struct { + char *letter; + char *signature_type_name; + char *gl_c_type_name; + char *c_type_name; } ForIsKnownArgVector; #define N_ELEMENTS(x) (sizeof(x)/sizeof(x[0])) #define N_FIELDS_IN_ARG_VECTOR 4 - -typedef struct -{ - char* func_name; - char* signature_type_name; +typedef struct { + char *func_name; + char *signature_type_name; } KnownLastArgFunc; -static KnownLastArgFunc knownLastArgFuncs[] = -{ -{"glFogCoordfv", "TYPE_1FLOAT"}, -{"glFogCoorddv", "TYPE_1DOUBLE"}, -{"glFogCoordfvEXT", "TYPE_1FLOAT"}, -{"glFogCoorddvEXT", "TYPE_1DOUBLE"}, -{"glFogCoordhvNV", "TYPE_1USHORT"}, - -{"glGetFenceivNV", "TYPE_OUT_1INT"}, - -{"glGetTexLevelParameteriv", "TYPE_OUT_1INT" }, -{"glGetTexLevelParameterfv", "TYPE_OUT_1FLOAT" }, - -{"glGetRenderbufferParameterivEXT", "TYPE_OUT_1INT"}, -{"glGetFramebufferAttachmentParameterivEXT", "TYPE_OUT_1INT"}, -{"glGetFinalCombinerInputParameterivNV", "TYPE_OUT_1INT"}, -{"glGetCombinerOutputParameterivNV", "TYPE_OUT_1INT"}, -{"glGetCombinerInputParameterivNV", "TYPE_OUT_1INT"}, -{"glGetOcclusionQueryivNV", "TYPE_OUT_1INT"}, -{"glGetOcclusionQueryuivNV", "TYPE_OUT_1UINT"}, -{"glGetObjectParameterivARB", "TYPE_OUT_1INT"}, -{"glGetQueryivARB", "TYPE_OUT_1INT"}, -{"glGetQueryiv", "TYPE_OUT_1INT"}, -{"glGetQueryObjectivARB", "TYPE_OUT_1INT"}, -{"glGetQueryObjectiv", "TYPE_OUT_1INT"}, -{"glGetQueryObjectuivARB", "TYPE_OUT_1UINT"}, -{"glGetQueryObjectuiv", "TYPE_OUT_1UINT"}, -{"glGetProgramivARB", "TYPE_OUT_1INT"}, -{"glGetProgramiv", "TYPE_OUT_1INT"}, -{"glGetProgramivNV", "TYPE_OUT_1INT"}, -{"glGetShaderiv", "TYPE_OUT_1INT"}, - -{"glCombinerParameterfvNV", "TYPE_1FLOAT"}, -{"glCombinerParameterivNV", "TYPE_1INT"}, - -{"glGetFinalCombinerInputParameterfvNV", "TYPE_OUT_1FLOAT"}, -{"glGetCombinerOutputParameterfvNV", "TYPE_OUT_1FLOAT"}, -{"glGetCombinerInputParameterfvNV", "TYPE_OUT_1FLOAT"}, -{"glGetObjectParameterfvARB", "TYPE_OUT_1FLOAT"}, - -{"glCombinerStageParameterfvNV", "TYPE_4FLOAT"}, -{"glGetCombinerStageParameterfvNV", "TYPE_OUT_4FLOAT"}, - -{"glTexBumpParameterivATI", "TYPE_1INT"}, -{"glTexBumpParameterfvATI", "TYPE_1FLOAT"}, -{"glGetTexBumpParameterivATI", "TYPE_OUT_1INT"}, -{"glGetTexBumpParameterfvATI", "TYPE_OUT_1FLOAT"}, - -{"glGetProgramLocalParameterfvARB", "TYPE_OUT_4FLOAT"}, -{"glGetProgramLocalParameterdvARB", "TYPE_OUT_4DOUBLE"}, -{"glGetProgramEnvParameterfvARB", "TYPE_OUT_4FLOAT"}, -{"glGetProgramEnvParameterdvARB", "TYPE_OUT_4DOUBLE"}, -{"glGetProgramLocalParameterIivNV", "TYPE_OUT_1INT"}, -{"glGetProgramLocalParameterIuivNV", "TYPE_OUT_1UINT"}, -{"glGetProgramEnvParameterIivNV", "TYPE_OUT_1INT"}, -{"glGetProgramEnvParameterIuivNV", "TYPE_OUT_1UINT"}, - -{"glGetProgramParameterfvNV", "TYPE_OUT_4FLOAT"}, -{"glGetProgramParameterdvNV", "TYPE_OUT_4DOUBLE"}, -{"glGetProgramNamedParameterfvNV", "TYPE_OUT_4FLOAT"}, -{"glGetProgramNamedParameterdvNV", "TYPE_OUT_4DOUBLE"}, - -{"glCullParameterfvEXT", "TYPE_4FLOAT"}, -{"glCullParameterdvEXT", "TYPE_4DOUBLE"}, - -{"glGetTrackMatrixivNV", "TYPE_OUT_1INT"}, -{"glExecuteProgramNV", "TYPE_4FLOAT"}, - -{"glEdgeFlagv", "TYPE_1UCHAR"}, - -{"glClipPlane", "TYPE_4DOUBLE"}, -{"glGetClipPlane", "TYPE_OUT_4DOUBLE"}, - -{"glSetFragmentShaderConstantATI", "TYPE_4FLOAT"}, - -{"glGetObjectBufferfvATI", "TYPE_OUT_1FLOAT"}, -{"glGetObjectBufferivATI", "TYPE_OUT_1INT"}, -{"glGetArrayObjectfvATI", "TYPE_OUT_1FLOAT"}, -{"glGetArrayObjectivATI", "TYPE_OUT_1INT"}, -{"glGetVariantArrayObjectfvATI", "TYPE_OUT_1FLOAT"}, -{"glGetVariantArrayObjectivATI", "TYPE_OUT_1INT"}, -{"glGetVertexAttribArrayObjectfvATI", "TYPE_OUT_1FLOAT"}, -{"glGetVertexAttribArrayObjectivATI", "TYPE_OUT_1INT"}, - -{"glPixelTransformParameterivEXT", "TYPE_1INT"}, -{"glPixelTransformParameterfvEXT", "TYPE_1FLOAT"}, -{"glGetPixelTransformParameterivEXT", "TYPE_OUT_1INT"}, -{"glGetPixelTransformParameterfvEXT", "TYPE_OUT_1FLOAT"}, - -{"glColorTableParameterfv", "TYPE_4FLOAT"}, -{"glColorTableParameteriv", "TYPE_4INT"}, -{"glGetColorTableParameterfv", "TYPE_OUT_4FLOAT"}, -{"glGetColorTableParameteriv", "TYPE_OUT_4INT"}, -{"glColorTableParameterfvEXT", "TYPE_4FLOAT"}, -{"glColorTableParameterivEXT", "TYPE_4INT"}, -{"glGetColorTableParameterfvEXT", "TYPE_OUT_4FLOAT"}, -{"glGetColorTableParameterivEXT", "TYPE_OUT_4INT"}, - -{"glGetMinmaxParameterfv", "TYPE_OUT_1FLOAT"}, -{"glGetMinmaxParameteriv", "TYPE_OUT_1INT"}, -{"glGetHistogramParameterfv", "TYPE_OUT_1FLOAT"}, -{"glGetHistogramParameteriv", "TYPE_OUT_1INT"}, -{"glGetMinmaxParameterfvEXT", "TYPE_OUT_1FLOAT"}, -{"glGetMinmaxParameterivEXT", "TYPE_OUT_1INT"}, -{"glGetHistogramParameterfvEXT", "TYPE_OUT_1FLOAT"}, -{"glGetHistogramParameterivEXT", "TYPE_OUT_1INT"}, +static KnownLastArgFunc knownLastArgFuncs[] = { + {"glFogCoordfv", "TYPE_1FLOAT"}, + {"glFogCoorddv", "TYPE_1DOUBLE"}, + {"glFogCoordfvEXT", "TYPE_1FLOAT"}, + {"glFogCoorddvEXT", "TYPE_1DOUBLE"}, + {"glFogCoordhvNV", "TYPE_1USHORT"}, + + {"glGetFenceivNV", "TYPE_OUT_1INT"}, + + {"glGetTexLevelParameteriv", "TYPE_OUT_1INT"}, + {"glGetTexLevelParameterfv", "TYPE_OUT_1FLOAT"}, + + {"glGetRenderbufferParameterivEXT", "TYPE_OUT_1INT"}, + {"glGetFramebufferAttachmentParameterivEXT", "TYPE_OUT_1INT"}, + {"glGetFinalCombinerInputParameterivNV", "TYPE_OUT_1INT"}, + {"glGetCombinerOutputParameterivNV", "TYPE_OUT_1INT"}, + {"glGetCombinerInputParameterivNV", "TYPE_OUT_1INT"}, + {"glGetOcclusionQueryivNV", "TYPE_OUT_1INT"}, + {"glGetOcclusionQueryuivNV", "TYPE_OUT_1UINT"}, + {"glGetObjectParameterivARB", "TYPE_OUT_1INT"}, + {"glGetQueryivARB", "TYPE_OUT_1INT"}, + {"glGetQueryiv", "TYPE_OUT_1INT"}, + {"glGetQueryObjectivARB", "TYPE_OUT_1INT"}, + {"glGetQueryObjectiv", "TYPE_OUT_1INT"}, + {"glGetQueryObjectuivARB", "TYPE_OUT_1UINT"}, + {"glGetQueryObjectuiv", "TYPE_OUT_1UINT"}, + {"glGetProgramivARB", "TYPE_OUT_1INT"}, + {"glGetProgramiv", "TYPE_OUT_1INT"}, + {"glGetProgramivNV", "TYPE_OUT_1INT"}, + {"glGetShaderiv", "TYPE_OUT_1INT"}, + + {"glCombinerParameterfvNV", "TYPE_1FLOAT"}, + {"glCombinerParameterivNV", "TYPE_1INT"}, + + {"glGetFinalCombinerInputParameterfvNV", "TYPE_OUT_1FLOAT"}, + {"glGetCombinerOutputParameterfvNV", "TYPE_OUT_1FLOAT"}, + {"glGetCombinerInputParameterfvNV", "TYPE_OUT_1FLOAT"}, + {"glGetObjectParameterfvARB", "TYPE_OUT_1FLOAT"}, + + {"glCombinerStageParameterfvNV", "TYPE_4FLOAT"}, + {"glGetCombinerStageParameterfvNV", "TYPE_OUT_4FLOAT"}, + + {"glTexBumpParameterivATI", "TYPE_1INT"}, + {"glTexBumpParameterfvATI", "TYPE_1FLOAT"}, + {"glGetTexBumpParameterivATI", "TYPE_OUT_1INT"}, + {"glGetTexBumpParameterfvATI", "TYPE_OUT_1FLOAT"}, + + {"glGetProgramLocalParameterfvARB", "TYPE_OUT_4FLOAT"}, + {"glGetProgramLocalParameterdvARB", "TYPE_OUT_4DOUBLE"}, + {"glGetProgramEnvParameterfvARB", "TYPE_OUT_4FLOAT"}, + {"glGetProgramEnvParameterdvARB", "TYPE_OUT_4DOUBLE"}, + {"glGetProgramLocalParameterIivNV", "TYPE_OUT_1INT"}, + {"glGetProgramLocalParameterIuivNV", "TYPE_OUT_1UINT"}, + {"glGetProgramEnvParameterIivNV", "TYPE_OUT_1INT"}, + {"glGetProgramEnvParameterIuivNV", "TYPE_OUT_1UINT"}, + + {"glGetProgramParameterfvNV", "TYPE_OUT_4FLOAT"}, + {"glGetProgramParameterdvNV", "TYPE_OUT_4DOUBLE"}, + {"glGetProgramNamedParameterfvNV", "TYPE_OUT_4FLOAT"}, + {"glGetProgramNamedParameterdvNV", "TYPE_OUT_4DOUBLE"}, + + {"glCullParameterfvEXT", "TYPE_4FLOAT"}, + {"glCullParameterdvEXT", "TYPE_4DOUBLE"}, + + {"glGetTrackMatrixivNV", "TYPE_OUT_1INT"}, + {"glExecuteProgramNV", "TYPE_4FLOAT"}, + + {"glEdgeFlagv", "TYPE_1UCHAR"}, + + {"glClipPlane", "TYPE_4DOUBLE"}, + {"glGetClipPlane", "TYPE_OUT_4DOUBLE"}, + + {"glSetFragmentShaderConstantATI", "TYPE_4FLOAT"}, + + {"glGetObjectBufferfvATI", "TYPE_OUT_1FLOAT"}, + {"glGetObjectBufferivATI", "TYPE_OUT_1INT"}, + {"glGetArrayObjectfvATI", "TYPE_OUT_1FLOAT"}, + {"glGetArrayObjectivATI", "TYPE_OUT_1INT"}, + {"glGetVariantArrayObjectfvATI", "TYPE_OUT_1FLOAT"}, + {"glGetVariantArrayObjectivATI", "TYPE_OUT_1INT"}, + {"glGetVertexAttribArrayObjectfvATI", "TYPE_OUT_1FLOAT"}, + {"glGetVertexAttribArrayObjectivATI", "TYPE_OUT_1INT"}, + + {"glPixelTransformParameterivEXT", "TYPE_1INT"}, + {"glPixelTransformParameterfvEXT", "TYPE_1FLOAT"}, + {"glGetPixelTransformParameterivEXT", "TYPE_OUT_1INT"}, + {"glGetPixelTransformParameterfvEXT", "TYPE_OUT_1FLOAT"}, + + {"glColorTableParameterfv", "TYPE_4FLOAT"}, + {"glColorTableParameteriv", "TYPE_4INT"}, + {"glGetColorTableParameterfv", "TYPE_OUT_4FLOAT"}, + {"glGetColorTableParameteriv", "TYPE_OUT_4INT"}, + {"glColorTableParameterfvEXT", "TYPE_4FLOAT"}, + {"glColorTableParameterivEXT", "TYPE_4INT"}, + {"glGetColorTableParameterfvEXT", "TYPE_OUT_4FLOAT"}, + {"glGetColorTableParameterivEXT", "TYPE_OUT_4INT"}, + + {"glGetMinmaxParameterfv", "TYPE_OUT_1FLOAT"}, + {"glGetMinmaxParameteriv", "TYPE_OUT_1INT"}, + {"glGetHistogramParameterfv", "TYPE_OUT_1FLOAT"}, + {"glGetHistogramParameteriv", "TYPE_OUT_1INT"}, + {"glGetMinmaxParameterfvEXT", "TYPE_OUT_1FLOAT"}, + {"glGetMinmaxParameterivEXT", "TYPE_OUT_1INT"}, + {"glGetHistogramParameterfvEXT", "TYPE_OUT_1FLOAT"}, + {"glGetHistogramParameterivEXT", "TYPE_OUT_1INT"}, /* Not sure at all for the 2 followingo ones ! */ -{"glGetBooleanIndexedvEXT", "TYPE_OUT_4UCHAR"}, -{"glGetIntegerIndexedvEXT", "TYPE_OUT_4INT"}, + {"glGetBooleanIndexedvEXT", "TYPE_OUT_4UCHAR"}, + {"glGetIntegerIndexedvEXT", "TYPE_OUT_4INT"}, -{"glReferencePlaneSGIX", "TYPE_4DOUBLE"}, + {"glReferencePlaneSGIX", "TYPE_4DOUBLE"}, -{"glGetTransformFeedbackVaryingNV", "TYPE_OUT_1INT"}, + {"glGetTransformFeedbackVaryingNV", "TYPE_OUT_1INT"}, }; -int is_known_arg_vector(FuncDesc* desc, char** p_signature_type_name, char** p_c_type_name) +int is_known_arg_vector(FuncDesc * desc, char **p_signature_type_name, + char **p_c_type_name) { - static ForIsKnownArgVector my_tab[] = - { - { "b", "CHAR", "GLbyte", "signed char" }, - { "Boolean", "CHAR", "GLboolean", "unsigned char" }, - { "s", "SHORT", "GLshort", "short" }, - { "i", "INT", "GLint", "int" }, - { "Integer", "INT", "GLint", "int" }, - { "ub", "CHAR", "GLubyte", "unsigned char" }, - { "h", "SHORT", "GLhalf", "unsigned short" }, - { "us", "SHORT", "GLushort", "unsigned short" }, - { "ui", "INT", "GLuint", "unsigned int" }, - { "Nb", "CHAR", "GLbyte", "signed char" }, - { "Ns", "SHORT", "GLshort", "short" }, - { "Ni", "INT", "GLint", "int" }, - { "Nub", "CHAR", "GLubyte", "unsigned char" }, - { "Nus", "SHORT", "GLushort", "unsigned short" }, - { "Nui", "INT", "GLuint", "unsigned int" }, - - { "f", "FLOAT", "GLfloat", "float" }, - { "Float", "FLOAT", "GLfloat", "float" }, - { "d", "DOUBLE", "GLdouble", "double" }, - }; - - if (desc->nargs == 0) - return 0; - - int i , j; - - if (strstr(desc->name, "glVertexAttribs") || - strstr(desc->name, "glProgramParameters") || - strstr(desc->name, "glProgramEnvParameters") || - strstr(desc->name, "glProgramLocalParameters") || - (strstr(desc->name, "glUniform") && (strstr(desc->name, "iv") || strstr(desc->name, "fv")))) - return 0; - - static char signatures[N_ELEMENTS(my_tab)][N_FIELDS_IN_ARG_VECTOR][20] = {0}; - char signature[10]; - - for(i=0;iname, knownLastArgFuncs[i].func_name) == 0) - { - if (p_signature_type_name) - { - *p_signature_type_name = knownLastArgFuncs[i].signature_type_name; - } - if (p_c_type_name) - { - if (strstr(knownLastArgFuncs[i].signature_type_name, "FLOAT")) - *p_c_type_name = "float"; - else if (strstr(knownLastArgFuncs[i].signature_type_name, "DOUBLE")) - *p_c_type_name = "double"; - else if (strstr(knownLastArgFuncs[i].signature_type_name, "UINT")) - *p_c_type_name = "unsigned int"; - else if (strstr(knownLastArgFuncs[i].signature_type_name, "INT")) - *p_c_type_name = "int"; - else if (strstr(knownLastArgFuncs[i].signature_type_name, "USHORT")) - *p_c_type_name = "unsigned short"; - else if (strstr(knownLastArgFuncs[i].signature_type_name, "SHORT")) - *p_c_type_name = "short"; - else if (strstr(knownLastArgFuncs[i].signature_type_name, "UCHAR")) - *p_c_type_name = "unsigned char"; - else if (strstr(knownLastArgFuncs[i].signature_type_name, "CHAR")) - *p_c_type_name = "char"; - else - assert(0); - } - return 1; + static ForIsKnownArgVector my_tab[] = { + {"b", "CHAR", "GLbyte", "signed char"}, + {"Boolean", "CHAR", "GLboolean", "unsigned char"}, + {"s", "SHORT", "GLshort", "short"}, + {"i", "INT", "GLint", "int"}, + {"Integer", "INT", "GLint", "int"}, + {"ub", "CHAR", "GLubyte", "unsigned char"}, + {"h", "SHORT", "GLhalf", "unsigned short"}, + {"us", "SHORT", "GLushort", "unsigned short"}, + {"ui", "INT", "GLuint", "unsigned int"}, + {"Nb", "CHAR", "GLbyte", "signed char"}, + {"Ns", "SHORT", "GLshort", "short"}, + {"Ni", "INT", "GLint", "int"}, + {"Nub", "CHAR", "GLubyte", "unsigned char"}, + {"Nus", "SHORT", "GLushort", "unsigned short"}, + {"Nui", "INT", "GLuint", "unsigned int"}, + + {"f", "FLOAT", "GLfloat", "float"}, + {"Float", "FLOAT", "GLfloat", "float"}, + {"d", "DOUBLE", "GLdouble", "double"}, + }; + + if (desc->nargs == 0) + return 0; + + int i, j; + + if (strstr(desc->name, "glVertexAttribs") || + strstr(desc->name, "glProgramParameters") || + strstr(desc->name, "glProgramEnvParameters") || + strstr(desc->name, "glProgramLocalParameters") || + (strstr(desc->name, "glUniform") + && (strstr(desc->name, "iv") || strstr(desc->name, "fv")))) + return 0; + + static char signatures[N_ELEMENTS(my_tab)][N_FIELDS_IN_ARG_VECTOR][20] = + { 0 }; + char signature[10]; + + for (i = 0; i < N_ELEMENTS(knownLastArgFuncs); i++) { + if (strcmp(desc->name, knownLastArgFuncs[i].func_name) == 0) { + if (p_signature_type_name) { + *p_signature_type_name = + knownLastArgFuncs[i].signature_type_name; + } + if (p_c_type_name) { + if (strstr(knownLastArgFuncs[i].signature_type_name, "FLOAT")) + *p_c_type_name = "float"; + else if (strstr + (knownLastArgFuncs[i].signature_type_name, "DOUBLE")) + *p_c_type_name = "double"; + else if (strstr + (knownLastArgFuncs[i].signature_type_name, "UINT")) + *p_c_type_name = "unsigned int"; + else if (strstr + (knownLastArgFuncs[i].signature_type_name, "INT")) + *p_c_type_name = "int"; + else if (strstr + (knownLastArgFuncs[i].signature_type_name, "USHORT")) + *p_c_type_name = "unsigned short"; + else if (strstr + (knownLastArgFuncs[i].signature_type_name, "SHORT")) + *p_c_type_name = "short"; + else if (strstr + (knownLastArgFuncs[i].signature_type_name, "UCHAR")) + *p_c_type_name = "unsigned char"; + else if (strstr + (knownLastArgFuncs[i].signature_type_name, "CHAR")) + *p_c_type_name = "char"; + else + assert(0); + } + return 1; + } } - } - - for(i=0;iname, "glIndex") && strstr(desc->name, "v")) - sprintf(signature, "%sv", my_tab[i].letter); - else - sprintf(signature, "%d%sv", j, my_tab[i].letter); - if (strstr(desc->name, signature) && - strstr(desc->args[desc->nargs - 1], my_tab[i].gl_c_type_name) && - strstr(desc->args[desc->nargs - 1], "*")) - { - if (p_signature_type_name) - { - if (signatures[i][j-1][0] == 0) - sprintf(signatures[i][j-1], "TYPE_%d%s", j, my_tab[i].signature_type_name); - *p_signature_type_name = signatures[i][j-1]; + + for (i = 0; i < N_ELEMENTS(my_tab); i++) { + for (j = 1; j <= N_FIELDS_IN_ARG_VECTOR; j++) { + if (strstr(desc->name, "glIndex") && strstr(desc->name, "v")) + sprintf(signature, "%sv", my_tab[i].letter); + else + sprintf(signature, "%d%sv", j, my_tab[i].letter); + if (strstr(desc->name, signature) && + strstr(desc->args[desc->nargs - 1], my_tab[i].gl_c_type_name) && + strstr(desc->args[desc->nargs - 1], "*")) { + if (p_signature_type_name) { + if (signatures[i][j - 1][0] == 0) + sprintf(signatures[i][j - 1], "TYPE_%d%s", j, + my_tab[i].signature_type_name); + *p_signature_type_name = signatures[i][j - 1]; + } + if (p_c_type_name) + *p_c_type_name = my_tab[i].c_type_name; + return 1; + } } - if (p_c_type_name) *p_c_type_name = my_tab[i].c_type_name; - return 1; - } } - } - return 0; + return 0; } -static void print_server_side_argument(FILE* server_stub, int j, char* glType) +static void print_server_side_argument(FILE * server_stub, int j, char *glType) { - const char* symbolic_type = get_type_string(glType); - if (strcmp(symbolic_type, "TYPE_CHAR") == 0) - fprintf(server_stub, "ARG_TO_CHAR(args[%d])", j); - else if (strcmp(symbolic_type, "TYPE_UNSIGNED_CHAR") == 0) - fprintf(server_stub, "ARG_TO_UNSIGNED_CHAR(args[%d])", j); - else if (strcmp(symbolic_type, "TYPE_SHORT") == 0) - fprintf(server_stub, "ARG_TO_SHORT(args[%d])", j); - else if (strcmp(symbolic_type, "TYPE_UNSIGNED_SHORT") == 0) - fprintf(server_stub, "ARG_TO_UNSIGNED_SHORT(args[%d])", j); - else if (strcmp(symbolic_type, "TYPE_INT") == 0) - fprintf(server_stub, "ARG_TO_INT(args[%d])", j); - else if (strcmp(symbolic_type, "TYPE_UNSIGNED_INT") == 0) - fprintf(server_stub, "ARG_TO_UNSIGNED_INT(args[%d])", j); - else if (strcmp(symbolic_type, "TYPE_FLOAT") == 0) - fprintf(server_stub, "ARG_TO_FLOAT(args[%d])", j); - else if (strcmp(symbolic_type, "TYPE_16FLOAT") == 0) - fprintf(server_stub, "(const float*)(args[%d])", j); - else if (strcmp(symbolic_type, "TYPE_DOUBLE") == 0) - fprintf(server_stub, "ARG_TO_DOUBLE(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_16DOUBLE") == 0) - fprintf(server_stub, "(const double*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_128UCHAR") == 0) - fprintf(server_stub, "(unsigned char*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_128UCHAR") == 0) - fprintf(server_stub, "(const unsigned char*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_NULL_TERMINATED_STRING") == 0) - fprintf(server_stub, "(const char*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_SHORT") == 0) - fprintf(server_stub, "(const short*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_UNSIGNED_SHORT") == 0) - fprintf(server_stub, "(const unsigned short*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_INT") == 0) - fprintf(server_stub, "(const int*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_UNSIGNED_INT") == 0) - fprintf(server_stub, "(const unsigned int*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_FLOAT") == 0) - fprintf(server_stub, "(const float*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_DOUBLE") == 0) - fprintf(server_stub, "(const double*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_CHAR") == 0) - fprintf(server_stub, "(const char*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_SIGNED_CHAR") == 0) - fprintf(server_stub, "(const signed char*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_VOID") == 0) - fprintf(server_stub, "(const void*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_ARRAY_UNSIGNED_CHAR") == 0) - fprintf(server_stub, "(const unsigned char*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_SHORT") == 0) - fprintf(server_stub, "(short*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_UNSIGNED_SHORT") == 0) - fprintf(server_stub, "(unsigned short*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_INT") == 0) - fprintf(server_stub, "(int*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_UNSIGNED_INT") == 0) - fprintf(server_stub, "(unsigned int*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_FLOAT") == 0) - fprintf(server_stub, "(float*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_DOUBLE") == 0) - fprintf(server_stub, "(double*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_VOID") == 0) - fprintf(server_stub, "(void*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_CHAR") == 0) - fprintf(server_stub, "(char*)(args[%d])", j); - else if ( strcmp(symbolic_type, "TYPE_OUT_ARRAY_UNSIGNED_CHAR") == 0) - fprintf(server_stub, "(unsigned char*)(args[%d])", j); - - else - { - fprintf(stderr, "Unknown : %s\n", symbolic_type); - assert(0); - } + const char *symbolic_type = get_type_string(glType); + if (strcmp(symbolic_type, "TYPE_CHAR") == 0) + fprintf(server_stub, "ARG_TO_CHAR(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_UNSIGNED_CHAR") == 0) + fprintf(server_stub, "ARG_TO_UNSIGNED_CHAR(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_SHORT") == 0) + fprintf(server_stub, "ARG_TO_SHORT(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_UNSIGNED_SHORT") == 0) + fprintf(server_stub, "ARG_TO_UNSIGNED_SHORT(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_INT") == 0) + fprintf(server_stub, "ARG_TO_INT(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_UNSIGNED_INT") == 0) + fprintf(server_stub, "ARG_TO_UNSIGNED_INT(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_FLOAT") == 0) + fprintf(server_stub, "ARG_TO_FLOAT(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_16FLOAT") == 0) + fprintf(server_stub, "(const float*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_DOUBLE") == 0) + fprintf(server_stub, "ARG_TO_DOUBLE(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_16DOUBLE") == 0) + fprintf(server_stub, "(const double*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_128UCHAR") == 0) + fprintf(server_stub, "(unsigned char*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_128UCHAR") == 0) + fprintf(server_stub, "(const unsigned char*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_NULL_TERMINATED_STRING") == 0) + fprintf(server_stub, "(const char*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_SHORT") == 0) + fprintf(server_stub, "(const short*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_UNSIGNED_SHORT") == 0) + fprintf(server_stub, "(const unsigned short*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_INT") == 0) + fprintf(server_stub, "(const int*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_UNSIGNED_INT") == 0) + fprintf(server_stub, "(const unsigned int*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_FLOAT") == 0) + fprintf(server_stub, "(const float*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_DOUBLE") == 0) + fprintf(server_stub, "(const double*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_CHAR") == 0) + fprintf(server_stub, "(const char*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_SIGNED_CHAR") == 0) + fprintf(server_stub, "(const signed char*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_VOID") == 0) + fprintf(server_stub, "(const void*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_ARRAY_UNSIGNED_CHAR") == 0) + fprintf(server_stub, "(const unsigned char*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_SHORT") == 0) + fprintf(server_stub, "(short*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_UNSIGNED_SHORT") == 0) + fprintf(server_stub, "(unsigned short*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_INT") == 0) + fprintf(server_stub, "(int*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_UNSIGNED_INT") == 0) + fprintf(server_stub, "(unsigned int*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_FLOAT") == 0) + fprintf(server_stub, "(float*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_DOUBLE") == 0) + fprintf(server_stub, "(double*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_VOID") == 0) + fprintf(server_stub, "(void*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_CHAR") == 0) + fprintf(server_stub, "(char*)(args[%d])", j); + else if (strcmp(symbolic_type, "TYPE_OUT_ARRAY_UNSIGNED_CHAR") == 0) + fprintf(server_stub, "(unsigned char*)(args[%d])", j); + + else { + fprintf(stderr, "Unknown : %s\n", symbolic_type); + assert(0); + } } -static const char* func_dealt_by_hand[500] = { NULL }; - - -static const char* ignore_func[] = -{ - "glGetPointerv", - "glRectdv", - "glRectfv", - "glRectiv", - "glRectsv", - "glMultiDrawArrays", - "glMultiDrawArraysEXT", - "glMultiDrawElements", - "glMultiDrawElementsEXT", - "glUnmapBuffer", - "glUnmapBufferARB", - "glLoadTransposeMatrixf", - "glLoadTransposeMatrixd", - "glMultTransposeMatrixf", - "glMultTransposeMatrixd", - "glLoadTransposeMatrixfARB", - "glLoadTransposeMatrixdARB", - "glMultTransposeMatrixfARB", - "glMultTransposeMatrixdARB", - - "glPixelDataRangeNV", - "glFlushPixelDataRangeNV", - "glVertexArrayRangeNV", - "glFlushVertexArrayRangeNV", - "glVertexWeightfEXT", - - "glGetBufferPointerv", - "glGetBufferPointervARB", - "glGetVertexAttribPointerv", - "glGetVertexAttribPointervARB", - "glVertexAttribPointer", - "glVertexAttribPointerARB", - "glGetVariantPointervEXT", - NULL, +static const char *func_dealt_by_hand[500] = { NULL }; + +static const char *ignore_func[] = { + "glGetPointerv", + "glRectdv", + "glRectfv", + "glRectiv", + "glRectsv", + "glMultiDrawArrays", + "glMultiDrawArraysEXT", + "glMultiDrawElements", + "glMultiDrawElementsEXT", + "glUnmapBuffer", + "glUnmapBufferARB", + "glLoadTransposeMatrixf", + "glLoadTransposeMatrixd", + "glMultTransposeMatrixf", + "glMultTransposeMatrixd", + "glLoadTransposeMatrixfARB", + "glLoadTransposeMatrixdARB", + "glMultTransposeMatrixfARB", + "glMultTransposeMatrixdARB", + + "glPixelDataRangeNV", + "glFlushPixelDataRangeNV", + "glVertexArrayRangeNV", + "glFlushVertexArrayRangeNV", + "glVertexWeightfEXT", + + "glGetBufferPointerv", + "glGetBufferPointervARB", + "glGetVertexAttribPointerv", + "glGetVertexAttribPointervARB", + "glVertexAttribPointer", + "glVertexAttribPointerARB", + "glGetVariantPointervEXT", + NULL, }; void get_func_dealt_by_hand() { - FILE* f = fopen(GL_INCLUDE_PATH"gl_func_perso.h", "r"); - char buffer[256]; - int i = 0; - char* c; - while(fgets(buffer, 256, f)) - { - if (strstr(buffer, "MAGIC_MACRO(")) - { - func_dealt_by_hand[i] = strdup(strstr(buffer, "MAGIC_MACRO(") + strlen("MAGIC_MACRO(")); - * strstr(func_dealt_by_hand[i], ")") = 0; - c = strstr(func_dealt_by_hand[i], "_"); - if (c && c != func_dealt_by_hand[i]) *c = 0; - i ++; + FILE *f = fopen(GL_INCLUDE_PATH "gl_func_perso.h", "r"); + char buffer[256]; + int i = 0; + char *c; + while (fgets(buffer, 256, f)) { + if (strstr(buffer, "MAGIC_MACRO(")) { + func_dealt_by_hand[i] = + strdup(strstr(buffer, "MAGIC_MACRO(") + strlen("MAGIC_MACRO(")); + *strstr(func_dealt_by_hand[i], ")") = 0; + c = strstr(func_dealt_by_hand[i], "_"); + if (c && c != func_dealt_by_hand[i]) + *c = 0; + i++; + } + } + fclose(f); + + int j = 0; + while (ignore_func[j]) { + func_dealt_by_hand[i] = ignore_func[j]; + i++; + j++; } - } - fclose(f); - - int j = 0; - while(ignore_func[j]) - { - func_dealt_by_hand[i] = ignore_func[j]; - i++; - j++; - } } -static const char* just_for_server_side_list[] = -{ - "glEnableClientState", - "glDisableClientState", - "glPushClientAttrib", - "glPopClientAttrib", - "glPixelStorei", - "glPixelStoref", - "glClientActiveTexture", - "glClientActiveTextureARB", - "glEnableVertexAttribArray", - "glEnableVertexAttribArrayARB", - "glDisableVertexAttribArray", - "glDisableVertexAttribArrayARB", - "glDrawElementArrayATI", - "glDrawRangeElementArrayATI", - "glGenSymbolsEXT", - "glFreeObjectBufferATI", - "glUnmapObjectBufferATI", - "glLockArraysEXT", - "glUnlockArraysEXT", - "glDepthFunc", - "glFogf", - "glFogi", - "glClipPlane", - "glGetClipPlane", - +static const char *just_for_server_side_list[] = { + "glEnableClientState", + "glDisableClientState", + "glPushClientAttrib", + "glPopClientAttrib", + "glPixelStorei", + "glPixelStoref", + "glClientActiveTexture", + "glClientActiveTextureARB", + "glEnableVertexAttribArray", + "glEnableVertexAttribArrayARB", + "glDisableVertexAttribArray", + "glDisableVertexAttribArrayARB", + "glDrawElementArrayATI", + "glDrawRangeElementArrayATI", + "glGenSymbolsEXT", + "glFreeObjectBufferATI", + "glUnmapObjectBufferATI", + "glLockArraysEXT", + "glUnlockArraysEXT", + "glDepthFunc", + "glFogf", + "glFogi", + "glClipPlane", + "glGetClipPlane", + /* begin of openquartz optimization */ #if 1 - "glMatrixMode", - "glOrtho", - "glFrustum", - "glPushMatrix", - "glPopMatrix", - "glLoadIdentity", - "glLoadMatrixd", - "glLoadMatrixf", - "glMultMatrixd", - "glMultMatrixf", - "glRotated", - "glRotatef", - "glScaled", - "glScalef", - "glTranslated", - "glTranslatef", + "glMatrixMode", + "glOrtho", + "glFrustum", + "glPushMatrix", + "glPopMatrix", + "glLoadIdentity", + "glLoadMatrixd", + "glLoadMatrixf", + "glMultMatrixd", + "glMultMatrixf", + "glRotated", + "glRotatef", + "glScaled", + "glScalef", + "glTranslated", + "glTranslatef", #endif /* end of openquartz optimization */ - - "glGetError", - "glActiveTextureARB", - - "glViewport", - "glScissor", - - "glBindBufferARB", - "glDeleteBuffersARB", - "glGenBuffersARB", - "glBufferDataARB", - "glBufferSubDataARB", - "glGetBufferSubDataARB", - "glGetBufferParameterivARB", - "glBindBuffer", - "glDeleteBuffers", - "glGenBuffers", - "glBufferData", - "glBufferSubData", - "glGetBufferSubData", - "glGetBufferParameteriv", - - "glPushAttrib", - "glPopAttrib", - "glEnable", - "glDisable", - "glIsEnabled", - "glBindTexture", - "glBindTextureEXT", - "glFogfv", - "glFogiv", - "glBitmap", - "glGetTexImage", - "glReadPixels", - "glDrawPixels", - "glSelectBuffer", - "glFeedbackBuffer", - - "glTexImage1D", - "glTexImage2D", - "glTexImage3D", - "glTexSubImage1D", - "glTexSubImage2D", - "glTexSubImage3D", - - "glTexImage3DEXT", - "glTexSubImage1DEXT", - "glTexSubImage2DEXT", - "glTexSubImage3DEXT", - - "glGetCompressedTexImage", - "glCompressedTexImage1D", - "glCompressedTexImage2D", - "glCompressedTexImage3D", - "glCompressedTexSubImage1D", - "glCompressedTexSubImage2D", - "glCompressedTexSubImage3D", - - "glGetCompressedTexImageARB", - "glCompressedTexImage1DARB", - "glCompressedTexImage2DARB", - "glCompressedTexImage3DARB", - "glCompressedTexSubImage1DARB", - "glCompressedTexSubImage2DARB", - "glCompressedTexSubImage3DARB", - - "glCallLists", - "glNewList", - "glDeleteLists", - "glGenLists", - - "glGenTextures", - "glDeleteTextures", - "glDeleteTexturesEXT", - "glMap1f", - "glMap1d", - "glMap2f", - "glMap2d", - "glGetMapdv", - "glGetMapfv", - "glGetMapiv", - "glGetBooleanv", - "glGetIntegerv", - "glGetFloatv", - "glGetDoublev", - - "glGetPixelMapfv", - "glGetPixelMapuiv", - "glGetPixelMapusv", - "glGetProgramStringARB", - "glGetProgramStringNV", - "glArrayElement", - "glDrawArrays", - "glDrawElements", - "glDrawRangeElements", - "glDrawRangeElementsEXT", - "glGetProgramInfoLog", - "glGetTexLevelParameteriv", - "glGetInfoLogARB", - "glGetShaderInfoLog", - "glGetAttachedObjectsARB", - "glGetAttachedShaders", - "glGetActiveUniformARB", - "glGetActiveUniform", - "glGetUniformLocationARB", - "glGetUniformLocation", - "glGetUniformfvARB", - "glGetUniformfv", - "glGetUniformivARB", - "glGetUniformiv", - "glGetUniformuivEXT", - "glGetShaderSourceARB", - "glGetShaderSource", - "glGetActiveAttribARB", - "glGetActiveAttrib", - "glGetAttribLocationARB", - "glGetAttribLocation", - - "glNewObjectBufferATI", - "glUpdateObjectBufferATI", - - "glSetLocalConstantEXT", - "glSetInvariantEXT", - "glVariantbvEXT", - "glVariantsvEXT", - "glVariantivEXT", - "glVariantfvEXT", - "glVariantdvEXT", - "glVariantubvEXT", - "glVariantusvEXT", - "glVariantuivEXT", - "glGetVariantBooleanvEXT", - "glGetVariantIntegervEXT", - "glGetVariantFloatvEXT", - "glGetInvariantBooleanvEXT", - "glGetInvariantIntegervEXT", - "glGetInvariantFloatvEXT", - "glGetLocalConstantBooleanvEXT", - "glGetLocalConstantIntegervEXT", - "glGetLocalConstantFloatvEXT", - - "glMatrixIndexubvARB", - "glMatrixIndexusvARB", - "glMatrixIndexuivARB", - - "glColorTable", - "glColorSubTable", - "glGetColorTable", - "glConvolutionFilter1D", - "glConvolutionFilter2D", - "glGetConvolutionFilter", - "glSeparableFilter2D", - "glGetSeparableFilter", - "glGetHistogram", - "glGetMinmax", - "glColorTableEXT", - "glColorSubTableEXT", - "glGetColorTableEXT", - "glConvolutionFilter1DEXT", - "glConvolutionFilter2DEXT", - "glGetConvolutionFilterEXT", - "glSeparableFilter2DEXT", - "glGetSeparableFilterEXT", - "glGetHistogramEXT", - "glGetMinmaxEXT", - - "glGetTexParameterfv", - - "glGetVertexAttribivARB", - "glGetVertexAttribfvARB", - "glGetVertexAttribdvARB", - "glGetVertexAttribiv", - "glGetVertexAttribfv", - "glGetVertexAttribdv", - - "glGetDetailTexFuncSGIS", - "glGetSharpenTexFuncSGIS", - - "fake_gluBuild2DMipmaps", - - "glRenderMode", - - "glEnableVariantClientStateEXT", - "glDisableVariantClientStateEXT", - - "glGetActiveVaryingNV", - - NULL, + + "glGetError", + "glActiveTextureARB", + + "glViewport", + "glScissor", + + "glBindBufferARB", + "glDeleteBuffersARB", + "glGenBuffersARB", + "glBufferDataARB", + "glBufferSubDataARB", + "glGetBufferSubDataARB", + "glGetBufferParameterivARB", + "glBindBuffer", + "glDeleteBuffers", + "glGenBuffers", + "glBufferData", + "glBufferSubData", + "glGetBufferSubData", + "glGetBufferParameteriv", + + "glPushAttrib", + "glPopAttrib", + "glEnable", + "glDisable", + "glIsEnabled", + "glBindTexture", + "glBindTextureEXT", + "glFogfv", + "glFogiv", + "glBitmap", + "glGetTexImage", + "glReadPixels", + "glDrawPixels", + "glSelectBuffer", + "glFeedbackBuffer", + + "glTexImage1D", + "glTexImage2D", + "glTexImage3D", + "glTexSubImage1D", + "glTexSubImage2D", + "glTexSubImage3D", + + "glTexImage3DEXT", + "glTexSubImage1DEXT", + "glTexSubImage2DEXT", + "glTexSubImage3DEXT", + + "glGetCompressedTexImage", + "glCompressedTexImage1D", + "glCompressedTexImage2D", + "glCompressedTexImage3D", + "glCompressedTexSubImage1D", + "glCompressedTexSubImage2D", + "glCompressedTexSubImage3D", + + "glGetCompressedTexImageARB", + "glCompressedTexImage1DARB", + "glCompressedTexImage2DARB", + "glCompressedTexImage3DARB", + "glCompressedTexSubImage1DARB", + "glCompressedTexSubImage2DARB", + "glCompressedTexSubImage3DARB", + + "glCallLists", + "glNewList", + "glDeleteLists", + "glGenLists", + + "glGenTextures", + "glDeleteTextures", + "glDeleteTexturesEXT", + "glMap1f", + "glMap1d", + "glMap2f", + "glMap2d", + "glGetMapdv", + "glGetMapfv", + "glGetMapiv", + "glGetBooleanv", + "glGetIntegerv", + "glGetFloatv", + "glGetDoublev", + + "glGetPixelMapfv", + "glGetPixelMapuiv", + "glGetPixelMapusv", + "glGetProgramStringARB", + "glGetProgramStringNV", + "glArrayElement", + "glDrawArrays", + "glDrawElements", + "glDrawRangeElements", + "glDrawRangeElementsEXT", + "glGetProgramInfoLog", + "glGetTexLevelParameteriv", + "glGetInfoLogARB", + "glGetShaderInfoLog", + "glGetAttachedObjectsARB", + "glGetAttachedShaders", + "glGetActiveUniformARB", + "glGetActiveUniform", + "glGetUniformLocationARB", + "glGetUniformLocation", + "glGetUniformfvARB", + "glGetUniformfv", + "glGetUniformivARB", + "glGetUniformiv", + "glGetUniformuivEXT", + "glGetShaderSourceARB", + "glGetShaderSource", + "glGetActiveAttribARB", + "glGetActiveAttrib", + "glGetAttribLocationARB", + "glGetAttribLocation", + + "glNewObjectBufferATI", + "glUpdateObjectBufferATI", + + "glSetLocalConstantEXT", + "glSetInvariantEXT", + "glVariantbvEXT", + "glVariantsvEXT", + "glVariantivEXT", + "glVariantfvEXT", + "glVariantdvEXT", + "glVariantubvEXT", + "glVariantusvEXT", + "glVariantuivEXT", + "glGetVariantBooleanvEXT", + "glGetVariantIntegervEXT", + "glGetVariantFloatvEXT", + "glGetInvariantBooleanvEXT", + "glGetInvariantIntegervEXT", + "glGetInvariantFloatvEXT", + "glGetLocalConstantBooleanvEXT", + "glGetLocalConstantIntegervEXT", + "glGetLocalConstantFloatvEXT", + + "glMatrixIndexubvARB", + "glMatrixIndexusvARB", + "glMatrixIndexuivARB", + + "glColorTable", + "glColorSubTable", + "glGetColorTable", + "glConvolutionFilter1D", + "glConvolutionFilter2D", + "glGetConvolutionFilter", + "glSeparableFilter2D", + "glGetSeparableFilter", + "glGetHistogram", + "glGetMinmax", + "glColorTableEXT", + "glColorSubTableEXT", + "glGetColorTableEXT", + "glConvolutionFilter1DEXT", + "glConvolutionFilter2DEXT", + "glGetConvolutionFilterEXT", + "glSeparableFilter2DEXT", + "glGetSeparableFilterEXT", + "glGetHistogramEXT", + "glGetMinmaxEXT", + + "glGetTexParameterfv", + + "glGetVertexAttribivARB", + "glGetVertexAttribfvARB", + "glGetVertexAttribdvARB", + "glGetVertexAttribiv", + "glGetVertexAttribfv", + "glGetVertexAttribdv", + + "glGetDetailTexFuncSGIS", + "glGetSharpenTexFuncSGIS", + + "fake_gluBuild2DMipmaps", + + "glRenderMode", + + "glEnableVariantClientStateEXT", + "glDisableVariantClientStateEXT", + + "glGetActiveVaryingNV", + + NULL, }; -static int just_for_server_side_func(char* funcname) +static int just_for_server_side_func(char *funcname) { - int i; - for(i=0;just_for_server_side_list[i];i++) - { - if (strcmp(just_for_server_side_list[i], funcname) == 0) - return 1; - } - return 0; + int i; + for (i = 0; just_for_server_side_list[i]; i++) { + if (strcmp(just_for_server_side_list[i], funcname) == 0) + return 1; + } + return 0; } -int parse(FILE* f, FuncDesc* funcDesc, int funcDescCount, int ignoreEXT) +int parse(FILE * f, FuncDesc * funcDesc, int funcDescCount, int ignoreEXT) { - char buffer[256]; - while(fgets(buffer, 256, f)) - { - - if (strncmp(buffer, "GLAPI", 5) == 0 && strstr(buffer, "APIENTRY") && strstr(buffer, "(")) - { - int i = 0; - int skip = 0; - if (func_dealt_by_hand[0] == 0) - { - get_func_dealt_by_hand(); - } - while (func_dealt_by_hand[i]) - { - if (strstr(buffer, func_dealt_by_hand[i])) - { - skip = 1; - break; - } - i++; - } - if (skip) - continue; - - char** args = malloc(15 * sizeof(char*)); - int narg = 0; - char* type = buffer + 6; - char* n = strstr(type, "GLAPIENTRY") ? strstr(type, "GLAPIENTRY") : strstr(type, "APIENTRY"); - int skip_length = strstr(type, "GLAPIENTRY") ? 11 : 9; - n[-1] = 0; - type = strdup(type); - n += skip_length; - char* fonc = n; - n = strstr(n, "("); - if (n[-1] == ' ') n[-1] = 0; - n[0] = 0; - fonc = strdup(fonc); - /*if (strstr(fonc, "glLockArraysEXT") || strstr(fonc, "glUnlockArraysEXT")) - { - } - else*/ - - - if (ignoreEXT == 1 && isExtByName(fonc)) - { - free(type); - free(fonc); - continue; - } - n++; - while(1) - { - char* virg = strstr(n, ","); - if (virg) - { - args[narg] = n; - virg[0] = 0; - args[narg] = get_arg_type(args[narg]); - narg++; - n = virg+1; - } - else - break; - } - while (strstr(n, ")") == 0) - { - fgets(buffer, 256, f); - n = buffer; - while(1) - { - char* virg = strstr(n, ","); - if (virg) - { + char buffer[256]; + while (fgets(buffer, 256, f)) { + + if (strncmp(buffer, "GLAPI", 5) == 0 && strstr(buffer, "APIENTRY") + && strstr(buffer, "(")) { + int i = 0; + int skip = 0; + if (func_dealt_by_hand[0] == 0) { + get_func_dealt_by_hand(); + } + while (func_dealt_by_hand[i]) { + if (strstr(buffer, func_dealt_by_hand[i])) { + skip = 1; + break; + } + i++; + } + if (skip) + continue; + + char **args = malloc(15 * sizeof(char *)); + int narg = 0; + char *type = buffer + 6; + char *n = + strstr(type, "GLAPIENTRY") ? strstr(type, + "GLAPIENTRY") : strstr(type, + "APIENTRY"); + int skip_length = strstr(type, "GLAPIENTRY") ? 11 : 9; + n[-1] = 0; + type = strdup(type); + n += skip_length; + char *fonc = n; + n = strstr(n, "("); + if (n[-1] == ' ') + n[-1] = 0; + n[0] = 0; + fonc = strdup(fonc); + /*if (strstr(fonc, "glLockArraysEXT") || strstr(fonc, "glUnlockArraysEXT")) + { + } + else */ + + if (ignoreEXT == 1 && isExtByName(fonc)) { + free(type); + free(fonc); + continue; + } + n++; + while (1) { + char *virg = strstr(n, ","); + if (virg) { + args[narg] = n; + virg[0] = 0; + args[narg] = get_arg_type(args[narg]); + narg++; + n = virg + 1; + } else + break; + } + while (strstr(n, ")") == 0) { + fgets(buffer, 256, f); + n = buffer; + while (1) { + char *virg = strstr(n, ","); + if (virg) { + args[narg] = n; + virg[0] = 0; + args[narg] = get_arg_type(args[narg]); + narg++; + n = virg + 1; + } else + break; + } + } + char *par = strstr(n, ")"); args[narg] = n; - virg[0] = 0; + par[0] = 0; args[narg] = get_arg_type(args[narg]); narg++; - n = virg+1; - } - else - break; - } - } - char* par = strstr(n, ")"); - args[narg] = n; - par[0] = 0; - args[narg] = get_arg_type(args[narg]); - narg++; - - - /*printf("%s %s (", type, fonc); - for(i=0;iargs[j], "*") == NULL) + int i; + if (strstr(funcDesc->args[j], "*") == NULL) + return 0; + for (i = 0; i < N_ELEMENTS(argDependingOnPreviousArgTab); i++) { + if (strstr(funcDesc->name, argDependingOnPreviousArgTab[i].str) + && j == argDependingOnPreviousArgTab[i].i) + return 1; + } return 0; - for(i=0;i< N_ELEMENTS(argDependingOnPreviousArgTab); i++) - { - if (strstr(funcDesc->name, argDependingOnPreviousArgTab[i].str) && j == argDependingOnPreviousArgTab[i].i) - return 1; - } - return 0; } -static void fprintf_prototype_args(FILE* f, FuncDesc* funcDesc) +static void fprintf_prototype_args(FILE * f, FuncDesc * funcDesc) { - int j; - for(j=0;jnargs;j++) - { - if (j != 0) fprintf(f,", "); - if (strstr(funcDesc->args[j], "[16]")) - { - if (strstr(funcDesc->args[j], "float")) - { - fprintf(f, "const GLfloat arg_%d[16]", j); - } - else if (strstr(funcDesc->args[j], "double")) - { - fprintf(f, "const GLdouble arg_%d[16]", j); - } - else - { - exit(-1); - } + int j; + for (j = 0; j < funcDesc->nargs; j++) { + if (j != 0) + fprintf(f, ", "); + if (strstr(funcDesc->args[j], "[16]")) { + if (strstr(funcDesc->args[j], "float")) { + fprintf(f, "const GLfloat arg_%d[16]", j); + } else if (strstr(funcDesc->args[j], "double")) { + fprintf(f, "const GLdouble arg_%d[16]", j); + } else { + exit(-1); + } + } else if (strstr(funcDesc->args[j], "[128]") + && strstr(funcDesc->args[j], "GLubyte")) + fprintf(f, + (strstr(funcDesc->args[j], "const")) ? + "const GLubyte* arg_%d" : "GLubyte* arg_%d", j); + else + fprintf(f, "%s arg_%d", funcDesc->args[j], j); } - else if (strstr(funcDesc->args[j], "[128]") && strstr(funcDesc->args[j], "GLubyte")) - fprintf(f, (strstr(funcDesc->args[j], "const")) ? "const GLubyte* arg_%d" : "GLubyte* arg_%d", j); - else - fprintf(f, "%s arg_%d", funcDesc->args[j], j); - } + if (j == 0) + fprintf(f, "void"); } -static void gen_mangled_gl(FuncDesc *funcs_p, int func_cnt) +static void gen_mangled_gl(FuncDesc * funcs_p, int func_cnt) { int i; FILE *header = fopen("gl_mangled.h", "w"); FILE *source = fopen("gl_mangled.c", "w"); - char** args; + char **args; assert(header && source); /* Manually add glGetString */ - args = malloc(1 * sizeof(char*)); + args = malloc(1 * sizeof(char *)); args[0] = strdup("GLenum"); funcs_p[func_cnt].type = strdup("const GLubyte *"); funcs_p[func_cnt].name = strdup("glGetString"); @@ -1150,13 +1107,14 @@ static void gen_mangled_gl(FuncDesc *funcs_p, int func_cnt) funcs_p[func_cnt].args = args; func_cnt++; - fprintf(header, "/* This file is generated by parse_gl_h.c - DO NOT EDIT ! */\n\n"); + fprintf(header, + "/* This file is generated by parse_gl_h.c - DO NOT EDIT ! */\n\n"); fprintf(header, "#include \n\n"); fprintf(header, "typedef struct mglHDL {\n"); for (i = 0; i < func_cnt; ++i) { fprintf(header, "\t%s (*%s)(", funcs_p[i].type, funcs_p[i].name); - if (funcs_p[i].nargs == 1 && !strncmp(funcs_p[i].args[0], "void", 4)) { + if (funcs_p[i].nargs == 1 && !strncmp(funcs_p[i].args[0], "void", 4)) { free(funcs_p[i].args[0]); funcs_p[i].nargs = 0; fprintf(header, "void"); @@ -1171,12 +1129,14 @@ static void gen_mangled_gl(FuncDesc *funcs_p, int func_cnt) fprintf(header, "int mgl_unload(void);\n\n"); for (i = 0; i < func_cnt; ++i) { - fprintf(header, "#define %s mgl_hdl.%s\n", funcs_p[i].name, funcs_p[i].name); + fprintf(header, "#define %s mgl_hdl.%s\n", funcs_p[i].name, + funcs_p[i].name); } fprintf(header, "\n"); - fprintf(source, "/* This file is generated by parse_gl_h.c - DO NOT EDIT ! */\n\n"); + fprintf(source, + "/* This file is generated by parse_gl_h.c - DO NOT EDIT ! */\n\n"); fprintf(source, "#include \n#include \"gl_mangled.h\"\n\n"); fprintf(source, "#ifdef _WIN32\n#include \n" "typedef HINSTANCE handle_t;\n#else\n#include \n" @@ -1184,20 +1144,19 @@ static void gen_mangled_gl(FuncDesc *funcs_p, int func_cnt) fprintf(source, "mglHDL mgl_hdl;\n"); fprintf(source, "static handle_t mgl_lib_hdl;\n\n"); - fprintf(source, "static inline handle_t mgl_load_lib(const char *libname)\n{\n" + fprintf(source, + "static inline handle_t mgl_load_lib(const char *libname)\n{\n" "#ifdef _WIN32\n\treturn LoadLibrary(libname);\n" "#else\n\treturn dlopen(libname, RTLD_LAZY | RTLD_LOCAL);\n" "#endif\n}\n\n"); fprintf(source, "static inline void *mgl_load_sym(const char *symname)\n{\n" "#ifdef _WIN32\n\treturn GetProcAddress(mgl_lib_hdl, symname);\n" - "#else\n\treturn dlsym(mgl_lib_hdl, symname);\n" - "#endif\n}\n\n"); + "#else\n\treturn dlsym(mgl_lib_hdl, symname);\n" "#endif\n}\n\n"); fprintf(source, "int mgl_unload(void)\n{\n" "#ifdef _WIN32\n\treturn FreeLibrary(mgl_lib_hdl);\n" - "#else\n\treturn dlclose(mgl_lib_hdl);\n" - "#endif\n}\n\n"); + "#else\n\treturn dlclose(mgl_lib_hdl);\n" "#endif\n}\n\n"); fprintf(source, "int mgl_load_symbols(const char *libname)\n{\n" "\tif (!(mgl_lib_hdl = mgl_load_lib(libname))) {\n" @@ -1226,380 +1185,372 @@ static void gen_mangled_gl(FuncDesc *funcs_p, int func_cnt) fclose(source); } -int main(int argc, char* argv[]) +int main(int argc, char *argv[]) { - FuncDesc funcDesc[3000]; - int funcDescCount = 0; - FILE* f; - - printf("***** path : %s\n", GL_INCLUDE_PATH"mesa_gl.h"); - f = fopen(GL_INCLUDE_PATH"mesa_gl.h", "r"); - assert(f); - /*if (!f) - f = fopen("/usr/include/GL/gl.h", "r");*/ - funcDescCount = parse(f, funcDesc, 0, 1); - fclose(f); - - if ((argc > 1) && !strncmp(argv[1], "mangle", 6)) { - gen_mangled_gl(funcDesc, funcDescCount); - return 0; - } - - f = fopen(GL_INCLUDE_PATH"mesa_glext.h", "r"); - assert(f); - /*if (!f) - f = fopen("/usr/include/GL/glext.h", "r");*/ - funcDescCount = parse(f, funcDesc, funcDescCount, 0); - fclose(f); - - FILE* header = fopen("gl_func.h", "w"); - FILE* client_stub = fopen("client_stub.c", "w"); - FILE* server_stub = fopen("server_stub.c", "w"); - - fprintf(header, "/* This is a generated file by parse_gl_h.c - DO NOT EDIT ! */\n\n"); - fprintf(header, "union gl_ret_type {\n" - "const char *s;\n" - "int i;\n" - "char c;\n" - "};\n"); - - fprintf(header, "#define COMPOSE(x,y) x##y\n"); - fprintf(header, "#define MAGIC_MACRO(x) COMPOSE(x,_func)\n"); - fprintf(header, "enum {\n" - "#include \"gl_func_perso.h\"\n"); - - fprintf(client_stub, "/* This is a generated file by parse_gl_h.c - DO NOT EDIT ! */\n\n"); - - fprintf(server_stub, "/* This is a generated file by parse_gl_h.c - DO NOT EDIT ! */\n\n"); - - int i; - for(i=0;i= 0) - { - j = funcDesc[i].nargs-1; - if (!is_arg_of_length_depending_on_previous_args(&funcDesc[i], j) && - strstr(funcDesc[i].args[j], "const GLchar") == NULL && - strstr(funcDesc[i].args[j], "[16]") == NULL) - { - pointer_of_unknown_size |= strstr(funcDesc[i].args[j], "*") != NULL; - pointer_of_unknown_size |= strstr(funcDesc[i].args[j], "[") != NULL; + FuncDesc funcDesc[3000]; + int funcDescCount = 0; + FILE *f; + + printf("***** path : %s\n", GL_INCLUDE_PATH "mesa_gl.h"); + f = fopen(GL_INCLUDE_PATH "mesa_gl.h", "r"); + assert(f); + /*if (!f) + f = fopen("/usr/include/GL/gl.h", "r"); */ + funcDescCount = parse(f, funcDesc, 0, 1); + fclose(f); + + if ((argc > 1) && !strncmp(argv[1], "mangle", 6)) { + gen_mangled_gl(funcDesc, funcDescCount); + return 0; + } + + f = fopen(GL_INCLUDE_PATH "mesa_glext.h", "r"); + assert(f); + /*if (!f) + f = fopen("/usr/include/GL/glext.h", "r"); */ + funcDescCount = parse(f, funcDesc, funcDescCount, 0); + fclose(f); + + FILE *header = fopen("gl_func.h", "w"); + FILE *client_stub = fopen("client_stub.c", "w"); + FILE *server_stub = fopen("server_stub.c", "w"); + + fprintf(header, + "/* This is a generated file by parse_gl_h.c - DO NOT EDIT ! */\n\n"); + fprintf(header, + "union gl_ret_type {\n" "const char *s;\n" "int i;\n" "char c;\n" + "};\n"); + + fprintf(header, "#define COMPOSE(x,y) x##y\n"); + fprintf(header, "#define MAGIC_MACRO(x) COMPOSE(x,_func)\n"); + fprintf(header, "enum {\n" "#include \"gl_func_perso.h\"\n"); + + fprintf(client_stub, + "/* This is a generated file by parse_gl_h.c - DO NOT EDIT ! */\n\n"); + + fprintf(server_stub, + "/* This is a generated file by parse_gl_h.c - DO NOT EDIT ! */\n\n"); + + int i; + for (i = 0; i < funcDescCount; i++) { + funcDesc[i].ok = 0; + char *name = funcDesc[i].name; + char *type = funcDesc[i].type; + if ((strcmp(type, "void") == 0 || strcmp(type, "GLboolean") == 0 || + strcmp(type, "GLuint") == 0 || strcmp(type, "GLint") == 0 || + strcmp(type, "GLenum") == 0) || strcmp(type, "GLhandleARB") == 0 || + strcmp(type, "GLhalf") == 0 || strcmp(type, "GLhalfNV") == 0) { + int pointer_of_unknown_size = 0; + int j; + + if (funcDesc[i].nargs == 1 + && strcmp(funcDesc[i].args[0], "void") == 0) { + funcDesc[i].nargs = 0; + } + for (j = 0; j < funcDesc[i].nargs - 1; j++) { + if (!is_arg_of_length_depending_on_previous_args + (&funcDesc[i], j) + && strstr(funcDesc[i].args[j], "const GLchar") == NULL + && strstr(funcDesc[i].args[j], "[16]") == NULL) { + pointer_of_unknown_size |= + strstr(funcDesc[i].args[j], "*") != NULL; + pointer_of_unknown_size |= + strstr(funcDesc[i].args[j], "[") != NULL; + } + } + + if (pointer_of_unknown_size == 0) { + char *signature_type_name; + if (is_known_arg_vector + (&funcDesc[i], &signature_type_name, NULL)) { + if (strstr(signature_type_name, "TYPE_OUT")) + funcDesc[i].has_out_parameters = 1; + } else { + if (funcDesc[i].nargs - 1 >= 0) { + j = funcDesc[i].nargs - 1; + if (!is_arg_of_length_depending_on_previous_args + (&funcDesc[i], j) + && strstr(funcDesc[i].args[j], + "const GLchar") == NULL + && strstr(funcDesc[i].args[j], "[16]") == NULL) { + pointer_of_unknown_size |= + strstr(funcDesc[i].args[j], "*") != NULL; + pointer_of_unknown_size |= + strstr(funcDesc[i].args[j], "[") != NULL; + } + } + } + } + if (pointer_of_unknown_size && funcDesc[i].nargs == 1) { + if (strstr(funcDesc[i].name, "Matrixf") + || strstr(funcDesc[i].name, "Matrixd")) { + free(funcDesc[i].args[0]); + if (strstr(funcDesc[i].name, "Matrixf")) + funcDesc[i].args[0] = strdup("GLfloat m[16]"); + else + funcDesc[i].args[0] = strdup("GLdouble m[16]"); + pointer_of_unknown_size = 0; + } else if (strcmp(funcDesc[i].name, "glPolygonStipple") == 0) { + free(funcDesc[i].args[0]); + funcDesc[i].args[0] = strdup("const GLubyte mask[128]"); + pointer_of_unknown_size = 0; + } else if (strcmp(funcDesc[i].name, "glGetPolygonStipple") == 0) { + free(funcDesc[i].args[0]); + funcDesc[i].args[0] = strdup("GLubyte mask[128]"); + funcDesc[i].has_out_parameters = 1; + pointer_of_unknown_size = 0; + } + } + if (just_for_server_side_func(name) || pointer_of_unknown_size == 0) { + fprintf(header, " %s_func,\n", funcDesc[i].name); + funcDesc[i].ok = 1; + if (just_for_server_side_func(name)) + funcDesc[i].just_for_server_side = 1; + for (j = 0; j < funcDesc[i].nargs; j++) { + if (strstr(get_type_string(funcDesc[i].args[j]), "OUT")) + funcDesc[i].has_out_parameters = 1; + } + } else { + fprintf(stderr, + "not handled either manually or automatically : %s\n", + funcDesc[i].name); } - } - } - } - if (pointer_of_unknown_size && funcDesc[i].nargs == 1) - { - if (strstr(funcDesc[i].name, "Matrixf") || strstr(funcDesc[i].name, "Matrixd")) - { - free(funcDesc[i].args[0]); - if (strstr(funcDesc[i].name, "Matrixf")) - funcDesc[i].args[0] = strdup("GLfloat m[16]"); - else - funcDesc[i].args[0] = strdup("GLdouble m[16]"); - pointer_of_unknown_size = 0; - } - else if (strcmp(funcDesc[i].name, "glPolygonStipple") == 0) - { - free(funcDesc[i].args[0]); - funcDesc[i].args[0] = strdup("const GLubyte mask[128]"); - pointer_of_unknown_size = 0; - } - else if (strcmp(funcDesc[i].name, "glGetPolygonStipple") == 0) - { - free(funcDesc[i].args[0]); - funcDesc[i].args[0] = strdup("GLubyte mask[128]"); - funcDesc[i].has_out_parameters = 1; - pointer_of_unknown_size = 0; - } - } - if (just_for_server_side_func(name) || pointer_of_unknown_size == 0) - { - fprintf(header, " %s_func,\n", funcDesc[i].name); - funcDesc[i].ok = 1; - if (just_for_server_side_func(name)) - funcDesc[i].just_for_server_side = 1; - for(j=0;j 0) fprintf(client_stub, ", "); - if (strstr(funcDesc[i].args[j], "*")) - { - fprintf(client_stub, "POINTER_TO_ARG(arg_%d)", j); + + fprintf(header, " GL_N_CALLS\n};\n"); + + fprintf(server_stub, + "static void execute_func(int func_number, void **args, union gl_ret_type *pret)\n"); + fprintf(server_stub, "{\n"); + fprintf(server_stub, " switch(func_number)\n"); + fprintf(server_stub, " {\n"); + + for (i = 0; i < funcDescCount; i++) { + if (funcDesc[i].ok) { + fprintf(header, "static const int %s_signature[] = { %s, %d, ", + funcDesc[i].name, + get_type_string(funcDesc[i].type), + funcDesc[i].has_out_parameters); + fprintf(header, "%d", funcDesc[i].nargs); + int j; + char *signature_type_name; + int n_args_to_check = + is_known_arg_vector(&funcDesc[i], &signature_type_name, + NULL) ? funcDesc[i].nargs - + 1 : funcDesc[i].nargs; + + for (j = 0; j < n_args_to_check; j++) { + if (is_arg_of_length_depending_on_previous_args + (&funcDesc[i], j)) { + fprintf(header, ", %s_OF_LENGTH_DEPENDING_ON_PREVIOUS_ARGS", + get_type_string(funcDesc[i].args[j])); + } else + fprintf(header, ", %s", + get_type_string(funcDesc[i].args[j])); } - else + + if (is_known_arg_vector(&funcDesc[i], &signature_type_name, NULL)) { + fprintf(header, ", %s", signature_type_name); + } + fprintf(header, "};\n"); + + if (funcDesc[i].just_for_server_side == 0) { + if (isExt(&funcDesc[i])) + fprintf(client_stub, "GLAPI %s APIENTRY EXT_FUNC(%s) (", + funcDesc[i].type, funcDesc[i].name); + else + fprintf(client_stub, "GLAPI %s APIENTRY %s(", + funcDesc[i].type, funcDesc[i].name); + fprintf_prototype_args(client_stub, &funcDesc[i]); + fprintf(client_stub, ")\n"); + fprintf(client_stub, "{\n"); + if (strcmp(funcDesc[i].type, "void") != 0) { + fprintf(client_stub, " %s ret;\n", funcDesc[i].type); + if (isExt(&funcDesc[i])) + fprintf(client_stub, " CHECK_PROC_WITH_RET(%s);\n", + funcDesc[i].name); + } else { + if (isExt(&funcDesc[i])) + fprintf(client_stub, " CHECK_PROC(%s);\n", + funcDesc[i].name); + } + + /* + fprintf(client_stub, " do_opengl_call(%s_func, %s", + funcDesc[i].name, (strcmp(funcDesc[i].type, "void") == 0) ? "NULL" : "&ret"); + for(j=0;j 0) + fprintf(client_stub, ", "); + if (strstr(funcDesc[i].args[j], "*")) { + fprintf(client_stub, "POINTER_TO_ARG(arg_%d)", j); + } else { + const char *symbolic_type = + get_type_string(funcDesc[i].args[j]); + if (strcmp(symbolic_type, "TYPE_CHAR") == 0) + fprintf(client_stub, "CHAR_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_UNSIGNED_CHAR") + == 0) + fprintf(client_stub, "UNSIGNED_CHAR_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_SHORT") == 0) + fprintf(client_stub, "SHORT_TO_ARG"); + else if (strcmp + (symbolic_type, + "TYPE_UNSIGNED_SHORT") == 0) + fprintf(client_stub, "UNSIGNED_SHORT_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_INT") == 0) + fprintf(client_stub, "INT_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_UNSIGNED_INT") + == 0) + fprintf(client_stub, "UNSIGNED_INT_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_FLOAT") == 0) + fprintf(client_stub, "FLOAT_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_16FLOAT") == 0) + fprintf(client_stub, "POINTER_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_DOUBLE") == 0) + fprintf(client_stub, "DOUBLE_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_16DOUBLE") == + 0) + fprintf(client_stub, "POINTER_TO_ARG"); + else if (strcmp(symbolic_type, "TYPE_128UCHAR") == 0 + || strcmp(symbolic_type, + "TYPE_OUT_128UCHAR") == 0) + fprintf(client_stub, "POINTER_TO_ARG"); + else { + fprintf(stderr, "Unknown : %s\n", + symbolic_type); + assert(0); + } + fprintf(client_stub, "(arg_%d)", j); + } + } + fprintf(client_stub, "};\n"); + } + + fprintf(client_stub, + " do_opengl_call(%s_func, %s, %s, NULL);\n", + funcDesc[i].name, + (strcmp(funcDesc[i].type, "void") == + 0) ? "NULL" : "&ret", + (funcDesc[i].nargs) ? "args" : "NULL"); + + if (strcmp(funcDesc[i].type, "void") != 0) { + fprintf(client_stub, " return ret;\n"); + } + fprintf(client_stub, "}\n\n"); + } + + fprintf(server_stub, " case %s_func:\n", funcDesc[i].name); + fprintf(server_stub, " {\n"); + + if (isExt(&funcDesc[i])) { + fprintf(server_stub, " GET_EXT_PTR(%s, %s, (", + funcDesc[i].type, funcDesc[i].name); + fprintf_prototype_args(server_stub, &funcDesc[i]); + fprintf(server_stub, "));\n"); + } + + fprintf(server_stub, " "); + + if (strcmp(funcDesc[i].type, "void") == 0) ; + else if (strcmp(get_type_string(funcDesc[i].type), "TYPE_INT") == 0 + || strcmp(get_type_string(funcDesc[i].type), + "TYPE_UNSIGNED_INT") == 0) + fprintf(server_stub, "pret->i = "); + else if (strcmp(get_type_string(funcDesc[i].type), "TYPE_CHAR") == 0 + || strcmp(get_type_string(funcDesc[i].type), + "TYPE_UNSIGNED_CHAR") == 0) + fprintf(server_stub, "pret->c = "); + else { + fprintf(stderr, "unknown ret type = %s\n", + get_type_string(funcDesc[i].type)); + exit(-1); + } + /*if (strstr(funcDesc[i].name, "EXT")) + { + char* dup = strdup(funcDesc[i].name); + *strstr(dup, "EXT") = 0; + fprintf(server_stub, "%s(", dup); + free(dup); + } + else */ { - const char* symbolic_type = get_type_string(funcDesc[i].args[j]); - if (strcmp(symbolic_type, "TYPE_CHAR") == 0) - fprintf(client_stub, "CHAR_TO_ARG"); - else if (strcmp(symbolic_type, "TYPE_UNSIGNED_CHAR") == 0) - fprintf(client_stub, "UNSIGNED_CHAR_TO_ARG"); - else if (strcmp(symbolic_type, "TYPE_SHORT") == 0) - fprintf(client_stub, "SHORT_TO_ARG"); - else if (strcmp(symbolic_type, "TYPE_UNSIGNED_SHORT") == 0) - fprintf(client_stub, "UNSIGNED_SHORT_TO_ARG"); - else if (strcmp(symbolic_type, "TYPE_INT") == 0) - fprintf(client_stub, "INT_TO_ARG"); - else if (strcmp(symbolic_type, "TYPE_UNSIGNED_INT") == 0) - fprintf(client_stub, "UNSIGNED_INT_TO_ARG"); - else if (strcmp(symbolic_type, "TYPE_FLOAT") == 0) - fprintf(client_stub, "FLOAT_TO_ARG"); - else if (strcmp(symbolic_type, "TYPE_16FLOAT") == 0) - fprintf(client_stub, "POINTER_TO_ARG"); - else if (strcmp(symbolic_type, "TYPE_DOUBLE") == 0) - fprintf(client_stub, "DOUBLE_TO_ARG"); - else if ( strcmp(symbolic_type, "TYPE_16DOUBLE") == 0) - fprintf(client_stub, "POINTER_TO_ARG"); - else if ( strcmp(symbolic_type, "TYPE_128UCHAR") == 0 || strcmp(symbolic_type, "TYPE_OUT_128UCHAR") == 0) - fprintf(client_stub, "POINTER_TO_ARG"); - else - { - fprintf(stderr, "Unknown : %s\n", symbolic_type); - assert(0); - } - fprintf(client_stub, "(arg_%d)", j); + if (isExt(&funcDesc[i])) + fprintf(server_stub, "ptr_func_%s(", funcDesc[i].name); + else + fprintf(server_stub, "%s(", funcDesc[i].name); } - } - fprintf(client_stub, "};\n"); - } - - fprintf(client_stub, " do_opengl_call(%s_func, %s, %s, NULL);\n", - funcDesc[i].name, (strcmp(funcDesc[i].type, "void") == 0) ? "NULL" : "&ret", - (funcDesc[i].nargs) ? "args" : "NULL"); - - if (strcmp(funcDesc[i].type, "void") != 0) - { - fprintf(client_stub, " return ret;\n"); - } - fprintf(client_stub, "}\n\n"); - } - - fprintf(server_stub, " case %s_func:\n", funcDesc[i].name); - fprintf(server_stub, " {\n"); - - if (isExt(&funcDesc[i])) - { - fprintf(server_stub, " GET_EXT_PTR(%s, %s, (", funcDesc[i].type, funcDesc[i].name); - fprintf_prototype_args(server_stub, &funcDesc[i]); - fprintf(server_stub, "));\n"); - } - - fprintf(server_stub, " "); - - if (strcmp(funcDesc[i].type, "void") == 0) - ; - else if (strcmp(get_type_string(funcDesc[i].type), "TYPE_INT") == 0 || - strcmp(get_type_string(funcDesc[i].type), "TYPE_UNSIGNED_INT") == 0) - fprintf(server_stub, "pret->i = "); - else if (strcmp(get_type_string(funcDesc[i].type), "TYPE_CHAR") == 0 || - strcmp(get_type_string(funcDesc[i].type), "TYPE_UNSIGNED_CHAR") == 0) - fprintf(server_stub, "pret->c = "); - else - { - fprintf(stderr, "unknown ret type = %s\n", get_type_string(funcDesc[i].type)); - exit(-1); - } - /*if (strstr(funcDesc[i].name, "EXT")) - { - char* dup = strdup(funcDesc[i].name); - *strstr(dup, "EXT") = 0; - fprintf(server_stub, "%s(", dup); - free(dup); - } - else*/ - { - if (isExt(&funcDesc[i])) - fprintf(server_stub, "ptr_func_%s(", funcDesc[i].name); - else - fprintf(server_stub, "%s(", funcDesc[i].name); - } - char* c_type_name; - if (is_known_arg_vector(&funcDesc[i], NULL, &c_type_name)) - { - for(j=0;j #include "tizen/src/debug_ch.h" -MULTI_DEBUG_CHANNEL(qemu, virtio-gl); - -int decode_call_int(ProcessStruct *p, char *in_args, int args_len, char *r_buffer); +MULTI_DEBUG_CHANNEL(qemu, virtio - gl); /* Uncomment to enable debugging - WARNING!!! changes ABI! */ //#define DEBUG_GLIO -typedef struct VirtIOGL -{ - VirtIODevice vdev; - VirtQueue *vq; +typedef struct VirtIOGL { + VirtIODevice vdev; + VirtQueue *vq; } VirtIOGL; -struct d_hdr -{ - int pid; - int rq_l; - int rrq_l; +struct d_hdr { + int pid; + int rq_l; + int rrq_l; #ifdef DEBUG_GLIO - int sum; + int sum; #endif }; @@ -64,165 +61,163 @@ struct d_hdr #define SIZE_IN_HEADER 4 #endif -static void virtio_gl_handle(VirtIODevice *vdev, VirtQueue *vq) +static void virtio_gl_handle(VirtIODevice * vdev, VirtQueue * vq) { - VirtQueueElement elem; - int nkill = 1; - - TRACE("virtio_gl_handle called. \n"); - - while(virtqueue_pop(vq, &elem)) { - struct d_hdr *hdr = (struct d_hdr*)elem.out_sg[0].iov_base; - ProcessStruct *process; - int i, remain; - int ret = 0; - - if(!elem.out_num) { - fprintf(stderr, "Bad packet\n"); - virtqueue_push(vq, &elem, ret); - virtio_notify(vdev, vq); - return; - } - - process = vmgl_get_process(hdr->pid); - - if(hdr->rq_l) { - - if(hdr->rrq_l) { - if(process->rq) { // Usually only the quit packet... - free(process->rq); - free(process->rrq); - } - // process->rq = process->rq_p = qemu_malloc(hdr->rq_l); - // process->rrq = process->rrq_p = qemu_malloc(hdr->rrq_l); - process->rq = process->rq_p = g_malloc(hdr->rq_l); - process->rrq = process->rrq_p = g_malloc(hdr->rrq_l); - process->rq_l = hdr->rq_l - SIZE_OUT_HEADER; - process->rrq_l = hdr->rrq_l; + VirtQueueElement elem; + int nkill = 1; + + TRACE("virtio_gl_handle called. \n"); + + while (virtqueue_pop(vq, &elem)) { + struct d_hdr *hdr = (struct d_hdr *)elem.out_sg[0].iov_base; + ProcessStruct *process; + int i, remain; + int ret = 0; + + if (!elem.out_num) { + fprintf(stderr, "Bad packet\n"); + virtqueue_push(vq, &elem, ret); + virtio_notify(vdev, vq); + return; + } + + process = vmgl_get_process(hdr->pid); + + if (hdr->rq_l) { + + if (hdr->rrq_l) { + if (process->rq) { // Usually only the quit packet... + free(process->rq); + free(process->rrq); + } + // process->rq = process->rq_p = qemu_malloc(hdr->rq_l); + // process->rrq = process->rrq_p = qemu_malloc(hdr->rrq_l); + process->rq = process->rq_p = g_malloc(hdr->rq_l); + process->rrq = process->rrq_p = g_malloc(hdr->rrq_l); + process->rq_l = hdr->rq_l - SIZE_OUT_HEADER; + process->rrq_l = hdr->rrq_l; #ifdef DEBUG_GLIO - process->sum = hdr->sum; + process->sum = hdr->sum; #endif - } + } - i = 0; - remain = process->rq_l - (process->rq_p - process->rq); - while(remain && i < elem.out_num){ - char *src = (char *)elem.out_sg[i].iov_base; - int ilen = elem.out_sg[i].iov_len; - int len = remain; + i = 0; + remain = process->rq_l - (process->rq_p - process->rq); + while (remain && i < elem.out_num) { + char *src = (char *)elem.out_sg[i].iov_base; + int ilen = elem.out_sg[i].iov_len; + int len = remain; - if(i == 0) { - src += SIZE_OUT_HEADER; - ilen -= SIZE_OUT_HEADER; - } + if (i == 0) { + src += SIZE_OUT_HEADER; + ilen -= SIZE_OUT_HEADER; + } - if(len > ilen) - len = ilen; + if (len > ilen) + len = ilen; - memcpy(process->rq_p, src, len); - process->rq_p += len; - remain -= len; - i++; - } + memcpy(process->rq_p, src, len); + process->rq_p += len; + remain -= len; + i++; + } - if(process->rq_p >= process->rq + process->rq_l) { + if (process->rq_p >= process->rq + process->rq_l) { #ifdef DEBUG_GLIO - int sum = 0; - for(i = 0; i < process->rq_l ; i++) - sum += process->rq[i]; - if(sum != process->sum) - fprintf(stderr, "Checksum fail\n"); + int sum = 0; + for (i = 0; i < process->rq_l; i++) + sum += process->rq[i]; + if (sum != process->sum) + fprintf(stderr, "Checksum fail\n"); #endif - *(int*)process->rrq = nkill = decode_call_int(process, - process->rq, /* command_buffer */ - process->rq_l, /* cmd buffer length */ - process->rrq + SIZE_IN_HEADER); /* return buffer */ + *(int *)process->rrq = nkill = decode_call_int(process, process->rq, /* command_buffer */ + process->rq_l, /* cmd buffer length */ + process->rrq + SIZE_IN_HEADER); /* return buffer */ - //qemu_free(process->rq); - g_free(process->rq); - process->rq = NULL; + //qemu_free(process->rq); + g_free(process->rq); + process->rq = NULL; #ifdef DEBUG_GLIO - sum = 0; - for(i = SIZE_IN_BUFFER; i < process->rrq_l ; i++) - sum += process->rrq[i]; - *(int*)(process->rrq+sizeof(int)) = sum; + sum = 0; + for (i = SIZE_IN_BUFFER; i < process->rrq_l; i++) + sum += process->rrq[i]; + *(int *)(process->rrq + sizeof(int)) = sum; #endif - } - } + } + } - if(hdr->rrq_l && process->rq == NULL) { + if (hdr->rrq_l && process->rq == NULL) { - i = 0; - remain = process->rrq_l - (process->rrq_p - process->rrq); - while(remain && i < elem.in_num) { - char *dst = elem.in_sg[i].iov_base; - int len = remain; - int ilen = elem.in_sg[i].iov_len; + i = 0; + remain = process->rrq_l - (process->rrq_p - process->rrq); + while (remain && i < elem.in_num) { + char *dst = elem.in_sg[i].iov_base; + int len = remain; + int ilen = elem.in_sg[i].iov_len; - if(len > ilen) - len = ilen; + if (len > ilen) + len = ilen; - memcpy(dst, process->rrq_p, len); - process->rrq_p += len; - remain -= len; - ret += len; - i++; - } + memcpy(dst, process->rrq_p, len); + process->rrq_p += len; + remain -= len; + ret += len; + i++; + } - if(remain <= 0) { - //qemu_free(process->rrq); - g_free(process->rrq); - if(!nkill) - gl_disconnect(process); - } - } + if (remain <= 0) { + //qemu_free(process->rrq); + g_free(process->rrq); + if (!nkill) + gl_disconnect(process); + } + } - virtqueue_push(vq, &elem, ret); + virtqueue_push(vq, &elem, ret); - virtio_notify(vdev, vq); - } + virtio_notify(vdev, vq); + } } -static uint32_t virtio_gl_get_features(VirtIODevice *vdev, uint32_t f) +static uint32_t virtio_gl_get_features(VirtIODevice * vdev, uint32_t f) { - return 0; + return 0; } -static void virtio_gl_save(QEMUFile *f, void *opaque) +static void virtio_gl_save(QEMUFile * f, void *opaque) { - VirtIOGL *s = opaque; + VirtIOGL *s = opaque; - virtio_save(&s->vdev, f); + virtio_save(&s->vdev, f); } -static int virtio_gl_load(QEMUFile *f, void *opaque, int version_id) +static int virtio_gl_load(QEMUFile * f, void *opaque, int version_id) { - VirtIOGL *s = opaque; + VirtIOGL *s = opaque; - if (version_id != 1) - return -EINVAL; + if (version_id != 1) + return -EINVAL; - virtio_load(&s->vdev, f); - return 0; + virtio_load(&s->vdev, f); + return 0; } -VirtIODevice *virtio_gl_init(DeviceState *dev) +VirtIODevice *virtio_gl_init(DeviceState * dev) { - VirtIOGL *s; + VirtIOGL *s; - s = (VirtIOGL *)virtio_common_init("virtio-gl", VIRTIO_ID_GL, - 0, sizeof(VirtIOGL)); - if (!s) - return NULL; + s = (VirtIOGL *) virtio_common_init("virtio-gl", VIRTIO_ID_GL, + 0, sizeof(VirtIOGL)); + if (!s) + return NULL; - s->vdev.get_features = virtio_gl_get_features; - s->vq = virtio_add_queue(&s->vdev, 128, virtio_gl_handle); - register_savevm(dev, "virtio-gl", -1, 1, virtio_gl_save, virtio_gl_load, s); + s->vdev.get_features = virtio_gl_get_features; + s->vq = virtio_add_queue(&s->vdev, 128, virtio_gl_handle); + register_savevm(dev, "virtio-gl", -1, 1, virtio_gl_save, virtio_gl_load, s); - return &s->vdev; + return &s->vdev; } - diff --git a/tizen/src/maru_display.c b/tizen/src/maru_display.c index 48d49b8391..c3af22dd51 100644 --- a/tizen/src/maru_display.c +++ b/tizen/src/maru_display.c @@ -1,7 +1,7 @@ /* * MARU display driver * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -59,12 +59,12 @@ void maru_display_init(DisplayState *ds) #ifndef CONFIG_USE_SHM /* sdl library */ dcl->dpy_update = qemu_ds_sdl_update; - dcl->dpy_resize = qemu_ds_sdl_resize; + dcl->dpy_resize = qemu_ds_sdl_switch; dcl->dpy_refresh = qemu_ds_sdl_refresh; #else /* shared memroy */ dcl->dpy_update = qemu_ds_shm_update; - dcl->dpy_resize = qemu_ds_shm_resize; + dcl->dpy_resize = qemu_ds_shm_switch; dcl->dpy_refresh = qemu_ds_shm_refresh; #endif @@ -91,26 +91,18 @@ void maru_display_fini(void) #endif } -void maruskin_init(uint64 swt_handle, int lcd_size_width, int lcd_size_height, bool is_resize) +void maruskin_init(uint64 swt_handle, + int lcd_size_width, int lcd_size_height) { #ifndef CONFIG_USE_SHM - maruskin_sdl_init(swt_handle, lcd_size_width, lcd_size_height, is_resize); + maruskin_sdl_init(swt_handle, lcd_size_width, lcd_size_height); #else - maruskin_shm_init(swt_handle, lcd_size_width, lcd_size_height, is_resize); + maruskin_shm_init(swt_handle, lcd_size_width, lcd_size_height); #endif } -DisplaySurface* get_qemu_display_surface(void) { -#ifndef CONFIG_USE_SHM - return maruskin_sdl_get_display(); -#else - //TODO: -#endif - - return NULL; -} - -MaruScreenshot* get_maru_screenshot(void) { +MaruScreenshot *get_maru_screenshot(void) +{ return maru_screenshot; } - +/* set_maru_screenshot() implemented in maruskin_operation.c */ diff --git a/tizen/src/maru_display.h b/tizen/src/maru_display.h index bebf480437..dbd5ac15c4 100644 --- a/tizen/src/maru_display.h +++ b/tizen/src/maru_display.h @@ -1,7 +1,7 @@ /* * MARU display driver * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -41,8 +41,10 @@ typedef struct MaruScreenshot { void maru_display_init(DisplayState *ds); void maru_display_fini(void); -void maruskin_init(uint64 swt_handle, int lcd_size_width, int lcd_size_height, bool is_resize); -DisplaySurface* get_qemu_display_surface(void); -MaruScreenshot* get_maru_screenshot(void); +void maruskin_init(uint64 swt_handle, + int lcd_size_width, int lcd_size_height); + +MaruScreenshot *get_maru_screenshot(void); +void set_maru_screenshot(DisplayState *surface); #endif /* __MARU_DISPLAY_H__ */ diff --git a/tizen/src/maru_sdl.c b/tizen/src/maru_sdl.c index b7bed2713d..b449b6d00c 100644 --- a/tizen/src/maru_sdl.c +++ b/tizen/src/maru_sdl.c @@ -34,25 +34,20 @@ #include #include "console.h" #include "maru_sdl.h" +#include "maru_display.h" #include "emul_state.h" -/* -#include "SDL_gfx/SDL_rotozoom.h" -#include "maru_sdl_rotozoom.h" -*/ +#include "emulator.h" #include "maru_finger.h" #include "hw/maru_pm.h" #include "hw/maru_brightness.h" +#include "hw/maru_overlay.h" #include "debug_ch.h" -/* #include "SDL_opengl.h" */ - -#ifdef MANGLE_OPENGL_SYMBOLS -#include "gl_mangled.h" -#endif MULTI_DEBUG_CHANNEL(tizen, maru_sdl); - -DisplaySurface* qemu_display_surface = NULL; +static QEMUBH *sdl_init_bh; +static QEMUBH *sdl_resize_bh; +static DisplayState *dpy_surface; static SDL_Surface *surface_screen; static SDL_Surface *surface_qemu; @@ -61,18 +56,12 @@ static SDL_Surface *rotated_screen; static double current_scale_factor = 1.0; static double current_screen_degree; -static int current_screen_width; -static int current_screen_height; -static int sdl_initialized; static int sdl_alteration; - -static int sdl_skip_update; - -#if 0 -static int sdl_opengl = 0; //0 : just SDL surface, 1 : using SDL with OpenGL -GLuint texture; -#endif +static unsigned int sdl_skip_update; +static unsigned int sdl_skip_count; +static int blank_cnt; +#define MAX_BLANK_FRAME_CNT 120 #define SDL_THREAD @@ -83,13 +72,12 @@ static pthread_cond_t sdl_cond = PTHREAD_COND_INITIALIZER; static int sdl_thread_initialized; #endif -#define SDL_FLAGS (SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_NOFRAME) +#define SDL_FLAGS (SDL_SWSURFACE | SDL_ASYNCBLIT | SDL_NOFRAME) #define SDL_BPP 32 /* Image processing functions using the pixman library */ static SDL_Surface *maru_do_pixman_scale(SDL_Surface *rz_src, - SDL_Surface *rz_dst, - int angle) + SDL_Surface *rz_dst) { pixman_image_t *src = NULL; pixman_image_t *dst = NULL; @@ -151,7 +139,8 @@ static SDL_Surface *maru_do_pixman_rotate(SDL_Surface *rz_src, break; case 90: pixman_f_transform_rotate(&matrix_f, NULL, 0.0, 1.0); - pixman_f_transform_translate(&matrix_f, NULL, (double)rz_dst->h, 0.0); + pixman_f_transform_translate(&matrix_f, NULL, + (double)rz_dst->h, 0.0); break; case 180: pixman_f_transform_rotate(&matrix_f, NULL, -1.0, 0.0); @@ -160,7 +149,8 @@ static SDL_Surface *maru_do_pixman_rotate(SDL_Surface *rz_src, break; case 270: pixman_f_transform_rotate(&matrix_f, NULL, 0.0, -1.0); - pixman_f_transform_translate(&matrix_f, NULL, 0.0, (double)rz_dst->w); + pixman_f_transform_translate(&matrix_f, NULL, + 0.0, (double)rz_dst->w); break; default: fprintf(stdout, "not supported angle factor (angle=%d)\n", angle); @@ -182,7 +172,8 @@ static SDL_Surface *maru_do_pixman_rotate(SDL_Surface *rz_src, return rz_dst; } -void qemu_ds_sdl_update(DisplayState *ds, int x, int y, int w, int h) +void qemu_ds_sdl_update(DisplayState *ds, + int x, int y, int w, int h) { /* call sdl update */ #ifdef SDL_THREAD @@ -196,14 +187,19 @@ void qemu_ds_sdl_update(DisplayState *ds, int x, int y, int w, int h) #endif } -void qemu_ds_sdl_resize(DisplayState *ds) +void qemu_ds_sdl_switch(DisplayState *ds) { - int w, h; + int console_width = 0, console_height = 0; - w = ds_get_width(ds); - h = ds_get_height(ds); + dpy_surface = ds; + console_width = ds_get_width(ds); + console_height = ds_get_height(ds); - INFO("qemu_ds_sdl_resize = (%d, %d)\n", w, h); + INFO("qemu_ds_sdl_switch : (%d, %d)\n", + console_width, console_height); + + sdl_skip_update = 0; + sdl_skip_count = 0; #ifdef SDL_THREAD pthread_mutex_lock(&sdl_mutex); @@ -215,8 +211,14 @@ void qemu_ds_sdl_resize(DisplayState *ds) } /* create surface_qemu */ - if (w == get_emul_lcd_width() && h == get_emul_lcd_height()) { - surface_qemu = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), w, h, + if (console_width == get_emul_lcd_width() && + console_height == get_emul_lcd_height()) { + INFO("create SDL screen : (%d, %d)\n", + console_width, console_height); + + surface_qemu = SDL_CreateRGBSurfaceFrom( + ds_get_data(ds), + console_width, console_height, ds_get_bits_per_pixel(ds), ds_get_linesize(ds), ds->surface->pf.rmask, @@ -224,8 +226,12 @@ void qemu_ds_sdl_resize(DisplayState *ds) ds->surface->pf.bmask, ds->surface->pf.amask); } else { - INFO("create blank screen = (%d, %d)\n", get_emul_lcd_width(), get_emul_lcd_height()); - surface_qemu = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, + INFO("create blank screen : (%d, %d)\n", + get_emul_lcd_width(), get_emul_lcd_height()); + + surface_qemu = SDL_CreateRGBSurface( + SDL_SWSURFACE, + console_width, console_height, ds_get_bits_per_pixel(ds), 0, 0, 0, 0); } @@ -237,59 +243,44 @@ void qemu_ds_sdl_resize(DisplayState *ds) ERR("Unable to set the RGBSurface: %s\n", SDL_GetError()); return; } - } -static int maru_sdl_poll_event(SDL_Event *ev) -{ - int ret = 0; - - if (sdl_initialized == 1) { - //pthread_mutex_lock(&sdl_mutex); - ret = SDL_PollEvent(ev); - //pthread_mutex_unlock(&sdl_mutex); - } - - return ret; -} void qemu_ds_sdl_refresh(DisplayState *ds) { - SDL_Event ev1, *ev = &ev1; - static uint32_t sdl_skip_count = 0; - - // surface may be NULL in init func. - qemu_display_surface = ds->surface; - - while (maru_sdl_poll_event(ev)) { - switch (ev->type) { - case SDL_VIDEORESIZE: - { - pthread_mutex_lock(&sdl_mutex); + if (sdl_alteration == 1) { + sdl_alteration = 0; + sdl_skip_update = 0; + sdl_skip_count = 0; + } - maruskin_sdl_init(0, get_emul_lcd_width(), get_emul_lcd_height(), true); + /* If the display is turned off, + the screen does not update until the display is turned on */ + if (sdl_skip_update && brightness_off) { + if (blank_cnt > MAX_BLANK_FRAME_CNT) { + /* do nothing */ + return; + } else if (blank_cnt == MAX_BLANK_FRAME_CNT) { + /* draw guide image */ + // TODO: + } else if (blank_cnt == 0) { + INFO("skipping of the display updating is started\n"); + } - pthread_mutex_unlock(&sdl_mutex); - vga_hw_invalidate(); - sdl_skip_update = 0; - sdl_skip_count = 0; - break; - } + blank_cnt++; - default: - break; + return; + } else { + if (blank_cnt != 0) { + INFO("skipping of the display updating is ended\n"); + blank_cnt = 0; } } - /* If the LCD is turned off, - the screen does not update until the LCD is turned on */ - if (sdl_skip_update && brightness_off) { - return; - } + vga_hw_update(); /* Usually, continuously updated. - When the LCD is turned off, + When the display is turned off, ten more updates the screen for a black screen. */ - vga_hw_update(); if (brightness_off) { if (++sdl_skip_count > 10) { sdl_skip_update = 1; @@ -319,344 +310,199 @@ void qemu_ds_sdl_refresh(DisplayState *ds) #endif } -//extern int capability_check_gl; -static void _sdl_init(void) -{ - int w, h, rwidth, rheight, temp; - - INFO("Set up a video mode with the specified width, height and bits-per-pixel\n"); - - //get current setting information and calculate screen size - rwidth = get_emul_lcd_width(); - rheight = get_emul_lcd_height(); - current_scale_factor = get_emul_win_scale(); - w = current_screen_width = rwidth * current_scale_factor; - h = current_screen_height = rheight * current_scale_factor; - - short rotaton_type = get_emul_rotation(); - if (rotaton_type == ROTATION_PORTRAIT) { - current_screen_degree = 0.0; - } else if (rotaton_type == ROTATION_LANDSCAPE) { - current_screen_degree = 90.0; - temp = w; - w = h; - h = temp; - temp = rwidth; - rwidth = rheight; - rheight = temp; - } else if (rotaton_type == ROTATION_REVERSE_PORTRAIT) { - current_screen_degree = 180.0; - } else if (rotaton_type == ROTATION_REVERSE_LANDSCAPE) { - current_screen_degree = 270.0; - temp = w; - w = h; - h = temp; - temp = rwidth; - rwidth = rheight; - rheight = temp; - } - -#if 0 - if (capability_check_gl != 0) { - ERR("GL check returned non-zero\n"); - surface_screen = NULL; - } else { - surface_screen = SDL_SetVideoMode(w, h, get_emul_sdl_bpp(), SDL_OPENGL); - } - - if (surface_screen == NULL) { - sdl_opengl = 0; - INFO("No OpenGL support on this system!??\n"); - ERR("%s\n", SDL_GetError()); -#endif - - surface_screen = SDL_SetVideoMode(w, h, get_emul_sdl_bpp(), SDL_FLAGS); - if (surface_screen == NULL) { - ERR("Could not open SDL display (%dx%dx%d): %s\n", w, h, get_emul_sdl_bpp(), SDL_GetError()); - return; - } -#if 0 - } else { - sdl_opengl = 1; - INFO("OpenGL is supported on this system.\n"); - } -#endif - - /* create buffer for image processing */ - SDL_FreeSurface(scaled_screen); - scaled_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, - w, h, get_emul_sdl_bpp(), - surface_qemu->format->Rmask, surface_qemu->format->Gmask, - surface_qemu->format->Bmask, surface_qemu->format->Amask); - SDL_FreeSurface(rotated_screen); - rotated_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, - rwidth, rheight, get_emul_sdl_bpp(), - surface_qemu->format->Rmask, surface_qemu->format->Gmask, - surface_qemu->format->Bmask, surface_qemu->format->Amask); - -#if 0 - if (sdl_opengl == 1) { - /* Set the OpenGL state */ - glClear(GL_COLOR_BUFFER_BIT); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, w, h, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - glViewport(0, 0, w, h); - glLoadIdentity(); - - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - //glGenerateMipmapEXT(GL_TEXTURE_2D); // GL_MIPMAP_LINEAR - } -#endif - - /* rearrange multi-touch finger points */ - if (get_emul_multi_touch_state()->multitouch_enable == 1 || - get_emul_multi_touch_state()->multitouch_enable == 2) { - rearrange_finger_points(get_emul_lcd_width(), get_emul_lcd_height(), - current_scale_factor, rotaton_type); - } -} - -#if 0 -static int point_degree = 0; -static void draw_outline_circle(int cx, int cy, int r, int num_segments) -{ - int ii; - float theta = 2 * 3.1415926 / (num_segments); - float c = cosf(theta);//precalculate the sine and cosine - float s = sinf(theta); - float t; - - float x = r;//we start at angle = 0 - float y = 0; - - glEnable(GL_LINE_STIPPLE); - glLoadIdentity(); - glColor3f(0.9, 0.9, 0.9); - glLineStipple(1, 0xcccc); - glLineWidth(3.f); - - glTranslatef(cx, cy, 0); - glRotated(point_degree++ % 360, 0, 0, 1); - - glBegin(GL_LINE_LOOP); - for(ii = 0; ii < num_segments; ii++) { - glVertex2f(x, y); //output vertex - - //apply the rotation matrix - t = x; - x = c * x - s * y; - y = s * t + c * y; - } - glEnd(); - - glDisable(GL_LINE_STIPPLE); -} - -static void draw_fill_circle(int cx, int cy, int r) -{ - glEnable(GL_POINT_SMOOTH); - glLoadIdentity(); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(0.1, 0.1, 0.1, 0.6); - glPointSize(r - 2); - - glBegin(GL_POINTS); - glVertex2f(cx, cy); - glEnd(); - - glDisable(GL_POINT_SMOOTH); - glDisable(GL_BLEND); -} -#endif - static void qemu_update(void) { - if (sdl_alteration == 1) { - sdl_alteration = 0; - _sdl_init(); - } else if (sdl_alteration == -1) { + if (sdl_alteration == -1) { SDL_FreeSurface(scaled_screen); SDL_FreeSurface(rotated_screen); SDL_FreeSurface(surface_qemu); surface_qemu = NULL; - SDL_Quit(); return; } if (surface_qemu != NULL) { - int i; - -#if 0 - if (sdl_opengl == 1) - { //gl surface - glEnable(GL_TEXTURE_2D); - glLoadIdentity(); - glColor3f(1.0, 1.0, 1.0); - glTexImage2D(GL_TEXTURE_2D, - 0, 3, surface_qemu->w, surface_qemu->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, surface_qemu->pixels); - - glClear(GL_COLOR_BUFFER_BIT); - - /* rotation */ - if (current_screen_degree == 270.0) { //reverse landscape - glRotated(90, 0, 0, 1); - glTranslatef(0, -current_screen_height, 0); - } else if (current_screen_degree == 180.0) { //reverse portrait - glRotated(180, 0, 0, 1); - glTranslatef(-current_screen_width, -current_screen_height, 0); - } else if (current_screen_degree == 90.0) { //landscape - glRotated(270, 0, 0, 1); - glTranslatef(-current_screen_width, 0, 0); - } + int i = 0; - glBegin(GL_QUADS); - glTexCoord2i(0, 0); - glVertex3f(0, 0, 0); - glTexCoord2i(1, 0); - glVertex3f(current_screen_width, 0, 0); - glTexCoord2i(1, 1); - glVertex3f(current_screen_width, current_screen_height, 0); - glTexCoord2i(0, 1); - glVertex3f(0, current_screen_height, 0); - glEnd(); - - glDisable(GL_TEXTURE_2D); - - /* draw multi-touch finger points */ - MultiTouchState *mts = get_emul_multi_touch_state(); - if (mts->multitouch_enable != 0) { - FingerPoint *finger = NULL; - int finger_point_size_half = mts->finger_point_size / 2; - - for (i = 0; i < mts->finger_cnt; i++) { - finger = get_finger_point_from_slot(i); - if (finger != NULL && finger->id != 0) { - draw_outline_circle(finger->origin_x, finger->origin_y, finger_point_size_half, 10); //TODO: optimize - draw_fill_circle(finger->origin_x, finger->origin_y, mts->finger_point_size); - } - } - } //end of draw multi-touch + set_maru_screenshot(dpy_surface); - glFlush(); + if (current_scale_factor != 1.0) { + rotated_screen = maru_do_pixman_rotate( + surface_qemu, rotated_screen, + (int)current_screen_degree); + scaled_screen = maru_do_pixman_scale( + rotated_screen, scaled_screen); - SDL_GL_SwapBuffers(); + SDL_BlitSurface(scaled_screen, NULL, surface_screen, NULL); } - else - { //sdl surface -#endif - if (current_scale_factor != 1.0) - { + else {/* current_scale_factor == 1.0 */ + if (current_screen_degree != 0.0) { rotated_screen = maru_do_pixman_rotate( surface_qemu, rotated_screen, (int)current_screen_degree); - scaled_screen = maru_do_pixman_scale( - rotated_screen, scaled_screen, - (int)current_screen_degree); - SDL_BlitSurface(scaled_screen, NULL, surface_screen, NULL); - } - else /* current_scale_factor == 1.0 */ - { - if (current_screen_degree != 0.0) { - rotated_screen = maru_do_pixman_rotate( - surface_qemu, rotated_screen, - (int)current_screen_degree); - SDL_BlitSurface(rotated_screen, NULL, surface_screen, NULL); - } else { - /* as-is */ - SDL_BlitSurface(surface_qemu, NULL, surface_screen, NULL); - } + + SDL_BlitSurface(rotated_screen, NULL, surface_screen, NULL); + } else { + /* as-is */ + SDL_BlitSurface(surface_qemu, NULL, surface_screen, NULL); } + } - /* draw multi-touch finger points */ - MultiTouchState *mts = get_emul_multi_touch_state(); - if (mts->multitouch_enable != 0 && mts->finger_point_surface != NULL) { - FingerPoint *finger = NULL; - int finger_point_size_half = mts->finger_point_size / 2; - SDL_Rect rect; - - for (i = 0; i < mts->finger_cnt; i++) { - finger = get_finger_point_from_slot(i); - if (finger != NULL && finger->id != 0) { - rect.x = finger->origin_x - finger_point_size_half; - rect.y = finger->origin_y - finger_point_size_half; - rect.w = rect.h = mts->finger_point_size; - - SDL_BlitSurface((SDL_Surface *)mts->finger_point_surface, NULL, surface_screen, &rect); - } + /* draw multi-touch finger points */ + MultiTouchState *mts = get_emul_multi_touch_state(); + if (mts->multitouch_enable != 0 && mts->finger_point_surface != NULL) { + FingerPoint *finger = NULL; + int finger_point_size_half = mts->finger_point_size / 2; + SDL_Rect rect; + + for (i = 0; i < mts->finger_cnt; i++) { + finger = get_finger_point_from_slot(i); + if (finger != NULL && finger->id != 0) { + rect.x = finger->origin_x - finger_point_size_half; + rect.y = finger->origin_y - finger_point_size_half; + rect.w = rect.h = mts->finger_point_size; + + SDL_BlitSurface( + (SDL_Surface *)mts->finger_point_surface, + NULL, surface_screen, &rect); } - } /* end of draw multi-touch */ - } + } + } /* end of draw multi-touch */ + } SDL_UpdateRect(surface_screen, 0, 0, 0, 0); } #ifdef SDL_THREAD -static void* run_qemu_update(void* arg) +static void *run_qemu_update(void *arg) { - while(1) { + while(1) { pthread_mutex_lock(&sdl_mutex); - pthread_cond_wait(&sdl_cond, &sdl_mutex); + pthread_cond_wait(&sdl_cond, &sdl_mutex); qemu_update(); pthread_mutex_unlock(&sdl_mutex); - } + } return NULL; } #endif -void maruskin_sdl_init(uint64 swt_handle, - int lcd_size_width, int lcd_size_height, bool is_resize) +static void maru_sdl_resize_bh(void *opaque) { - gchar SDL_windowhack[32]; - SDL_SysWMinfo info; - long window_id = swt_handle; + int surface_width = 0, surface_height = 0; + int display_width = 0, display_height = 0; + int temp = 0; - INFO("maru sdl initialization = %d\n", is_resize); + INFO("Set up a video mode with the specified width, " + "height and bits-per-pixel\n"); - if (is_resize == FALSE) { //once - sprintf(SDL_windowhack, "%ld", window_id); - g_setenv("SDL_WINDOWID", SDL_windowhack, 1); - INFO("register SDL environment variable. (SDL_WINDOWID = %s)\n", SDL_windowhack); +#ifdef SDL_THREAD + pthread_mutex_lock(&sdl_mutex); +#endif - if (SDL_Init(SDL_INIT_VIDEO) < 0 ) { - ERR("unable to init SDL: %s\n", SDL_GetError()); - } + sdl_alteration = 1; + sdl_skip_update = 0; - set_emul_lcd_size(lcd_size_width, lcd_size_height); - set_emul_sdl_bpp(SDL_BPP); + /* get current setting information and calculate screen size */ + display_width = get_emul_lcd_width(); + display_height = get_emul_lcd_height(); + current_scale_factor = get_emul_win_scale(); + + short rotaton_type = get_emul_rotation(); + if (rotaton_type == ROTATION_PORTRAIT) { + current_screen_degree = 0.0; + } else if (rotaton_type == ROTATION_LANDSCAPE) { + current_screen_degree = 90.0; + temp = display_width; + display_width = display_height; + display_height = temp; + } else if (rotaton_type == ROTATION_REVERSE_PORTRAIT) { + current_screen_degree = 180.0; + } else if (rotaton_type == ROTATION_REVERSE_LANDSCAPE) { + current_screen_degree = 270.0; + temp = display_width; + display_width = display_height; + display_height = temp; } - if (sdl_initialized == 0) { - sdl_initialized = 1; + surface_width = display_width * current_scale_factor; + surface_height = display_height * current_scale_factor; - //SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - init_multi_touch_state(); + surface_screen = SDL_SetVideoMode( + surface_width, surface_height, + get_emul_sdl_bpp(), SDL_FLAGS); -#ifndef _WIN32 - SDL_VERSION(&info.version); - SDL_GetWMInfo(&info); + INFO("SDL_SetVideoMode\n"); + + if (surface_screen == NULL) { + ERR("Could not open SDL display (%dx%dx%d) : %s\n", + surface_width, surface_height, + get_emul_sdl_bpp(), SDL_GetError()); + return; + } + + /* create buffer for image processing */ + SDL_FreeSurface(scaled_screen); + scaled_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, + surface_width, surface_height, + get_emul_sdl_bpp(), + surface_qemu->format->Rmask, + surface_qemu->format->Gmask, + surface_qemu->format->Bmask, + surface_qemu->format->Amask); + + SDL_FreeSurface(rotated_screen); + rotated_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, + display_width, display_height, + get_emul_sdl_bpp(), + surface_qemu->format->Rmask, + surface_qemu->format->Gmask, + surface_qemu->format->Bmask, + surface_qemu->format->Amask); + + /* rearrange multi-touch finger points */ + if (get_emul_multi_touch_state()->multitouch_enable == 1 || + get_emul_multi_touch_state()->multitouch_enable == 2) { + rearrange_finger_points(get_emul_lcd_width(), get_emul_lcd_height(), + current_scale_factor, rotaton_type); + } + +#ifdef SDL_THREAD + pthread_mutex_unlock(&sdl_mutex); #endif +} + +static void maru_sdl_init_bh(void *opaque) +{ + SDL_SysWMinfo info; + + INFO("SDL_Init\n"); + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + ERR("unable to init SDL: %s\n", SDL_GetError()); + //TODO: } - sdl_alteration = 1; +#ifndef _WIN32 + SDL_VERSION(&info.version); + SDL_GetWMInfo(&info); +#endif + + qemu_bh_schedule(sdl_resize_bh); #ifdef SDL_THREAD if (sdl_thread_initialized == 0) { sdl_thread_initialized = 1; - pthread_t thread_id; + INFO("sdl update thread create\n"); - if (pthread_create(&thread_id, NULL, run_qemu_update, NULL) != 0) { + + pthread_t thread_id; + if (pthread_create( + &thread_id, NULL, run_qemu_update, NULL) != 0) { ERR("pthread_create fail\n"); return; } @@ -664,17 +510,46 @@ void maruskin_sdl_init(uint64 swt_handle, #endif } +void maruskin_sdl_init(uint64 swt_handle, + int lcd_size_width, int lcd_size_height) +{ + gchar SDL_windowhack[32] = { 0, }; + long window_id = swt_handle; + + INFO("maru sdl init\n"); + + sdl_init_bh = qemu_bh_new(maru_sdl_init_bh, NULL); + sdl_resize_bh = qemu_bh_new(maru_sdl_resize_bh, NULL); + + sprintf(SDL_windowhack, "%ld", window_id); + g_setenv("SDL_WINDOWID", SDL_windowhack, 1); + + INFO("register SDL environment variable. " + "(SDL_WINDOWID = %s)\n", SDL_windowhack); + + set_emul_lcd_size(lcd_size_width, lcd_size_height); + set_emul_sdl_bpp(SDL_BPP); + init_multi_touch_state(); + + qemu_bh_schedule(sdl_init_bh); +} + void maruskin_sdl_quit(void) { + INFO("maru sdl quit\n"); + /* remove multi-touch finger points */ - get_emul_multi_touch_state()->multitouch_enable = 0; - clear_finger_slot(); cleanup_multi_touch_state(); -#if 0 - if (sdl_opengl == 1) { - glDeleteTextures(1, &texture); + if (sdl_init_bh != NULL) { + qemu_bh_delete(sdl_init_bh); } + if (sdl_resize_bh != NULL) { + qemu_bh_delete(sdl_resize_bh); + } + +#ifdef SDL_THREAD + pthread_mutex_lock(&sdl_mutex); #endif sdl_alteration = -1; @@ -682,26 +557,16 @@ void maruskin_sdl_quit(void) SDL_Quit(); #ifdef SDL_THREAD + pthread_mutex_unlock(&sdl_mutex); pthread_cond_destroy(&sdl_cond); #endif + pthread_mutex_destroy(&sdl_mutex); } - void maruskin_sdl_resize(void) { - SDL_Event ev; - - /* this fails if SDL is not initialized */ - memset(&ev, 0, sizeof(ev)); - ev.resize.type = SDL_VIDEORESIZE; + INFO("maru sdl resize\n"); - /* This function is thread safe, - and can be called from other threads safely. */ - SDL_PushEvent(&ev); + qemu_bh_schedule(sdl_resize_bh); } - -DisplaySurface* maruskin_sdl_get_display(void) { - return qemu_display_surface; -} - diff --git a/tizen/src/maru_sdl.h b/tizen/src/maru_sdl.h index 5ead7a3150..8d8f8bd5eb 100644 --- a/tizen/src/maru_sdl.h +++ b/tizen/src/maru_sdl.h @@ -1,9 +1,10 @@ /* * SDL_WINDOWID hack * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: + * Jinhyung Jo * GiWoong Kim * SeokYeon Hwang * YeongKyoon Lee @@ -36,15 +37,13 @@ #include #include "qemu-common.h" - void qemu_ds_sdl_update(DisplayState *ds, int x, int y, int w, int h); -void qemu_ds_sdl_resize(DisplayState *ds); +void qemu_ds_sdl_switch(DisplayState *ds); void qemu_ds_sdl_refresh(DisplayState *ds); -void maruskin_sdl_init(uint64 swt_handle, int lcd_size_width, int lcd_size_height, bool is_resize); +void maruskin_sdl_init(uint64 swt_handle, + int lcd_size_width, int lcd_size_height); void maruskin_sdl_resize(void); void maruskin_sdl_quit(void); -DisplaySurface* maruskin_sdl_get_display(void); - #endif /* MARU_SDL_H_ */ diff --git a/tizen/src/maru_shm.c b/tizen/src/maru_shm.c index dc9e9619a9..77b5c26764 100644 --- a/tizen/src/maru_shm.c +++ b/tizen/src/maru_shm.c @@ -40,7 +40,7 @@ void qemu_ds_shm_update(DisplayState *ds, int x, int y, int w, int h) //TODO: } -void qemu_ds_shm_resize(DisplayState *ds) +void qemu_ds_shm_switch(DisplayState *ds) { //TODO: } @@ -50,13 +50,12 @@ void qemu_ds_shm_refresh(DisplayState *ds) vga_hw_update(); } -void maruskin_shm_init(uint64 swt_handle, int lcd_size_width, int lcd_size_height, bool is_resize) +void maruskin_shm_init(uint64 swt_handle, + int lcd_size_width, int lcd_size_height) { - INFO("maru shm initialization = %d\n", is_resize); + INFO("maru shm initialization\n"); - if (is_resize == FALSE) { //once - set_emul_lcd_size(lcd_size_width, lcd_size_height); - set_emul_sdl_bpp(32); - } + set_emul_lcd_size(lcd_size_width, lcd_size_height); + set_emul_sdl_bpp(32); } diff --git a/tizen/src/maru_shm.h b/tizen/src/maru_shm.h index 12035b4aff..d68172ee99 100644 --- a/tizen/src/maru_shm.h +++ b/tizen/src/maru_shm.h @@ -35,8 +35,9 @@ void qemu_ds_shm_update(DisplayState *ds, int x, int y, int w, int h); -void qemu_ds_shm_resize(DisplayState *ds); +void qemu_ds_shm_switch(DisplayState *ds); void qemu_ds_shm_refresh(DisplayState *ds); -void maruskin_shm_init(uint64 swt_handle, int lcd_size_width, int lcd_size_height, bool is_resize); +void maruskin_shm_init(uint64 swt_handle, + int lcd_size_width, int lcd_size_height); #endif /* MARU_SHM_H_ */ diff --git a/tizen/src/mloop_event.c b/tizen/src/mloop_event.c index 1e6b37744c..03b1ff3532 100644 --- a/tizen/src/mloop_event.c +++ b/tizen/src/mloop_event.c @@ -306,7 +306,7 @@ static void mloop_evhandle_keyboard(long data) #ifdef TARGET_I386 static void mloop_evhandle_kbd_add(char *name) { - TRACE("mloop_evhandle_kbd_add\n"); + TRACE("try to add a keyboard device.\n"); if (name == NULL) { ERR("packet data is NULL.\n"); @@ -343,7 +343,7 @@ static void mloop_evhandle_kbd_add(char *name) static void mloop_evhandle_kbd_del(char *name) { - TRACE("mloop_evhandle_kbd_del\n"); + TRACE("try to remove a keyboard device.\n"); if (name == NULL) { ERR("packet data is NULL.\n"); @@ -382,7 +382,7 @@ static void mloop_evhandle_sdcard_attach(char *name) { char opts[PATH_MAX]; - INFO("mloop_evhandle_sdcard_attach\n"); + INFO("try to attach sdcard.\n"); if (name == NULL) { ERR("Packet data is NULL.\n"); @@ -402,18 +402,21 @@ static void mloop_evhandle_sdcard_attach(char *name) qdict_put(qdict, "opts", qstring_from_str(opts)); virtio_sdcard = pci_device_hot_add(cur_mon, qdict); - - INFO("hot add virtio storage device with [%s]\n", opts); - INFO("virtio-sdcard device: domain %d, bus %d, slot %d, function %d\n", + if (virtio_sdcard) { + INFO("hot add virtio storage device with [%s]\n", opts); + INFO("virtio-sdcard device: domain %d, bus %d, slot %d, function %d\n", pci_find_domain(virtio_sdcard->bus), pci_bus_num(virtio_sdcard->bus), PCI_SLOT(virtio_sdcard->devfn), PCI_FUNC(virtio_sdcard->devfn)); + } else { + ERR("failed to create a device for sdcard.\n"); + } QDECREF(qdict); } static void mloop_evhandle_sdcard_detach(char *name) { - INFO("mloop_evhandle_sdcard_detach\n"); + INFO("try to detach sdcard.\n"); if (name == NULL) { ERR("packet data is NULL.\n"); @@ -612,7 +615,6 @@ void mloop_evcmd_usbdisk(char *img) if (img) { if (strlen(img) > PACKET_LEN-5) { - // Need log ERR("The length of disk image path is greater than " "lenth of maximum packet.\n"); return; @@ -634,7 +636,6 @@ void mloop_evcmd_sdcard(char *img) if (img) { if (strlen(img) > PACKET_LEN-5) { - // Need log ERR("The length of disk image path is greater than " "lenth of maximum packet.\n"); return; @@ -718,4 +719,3 @@ void mloop_evcmd_ramdump(void) pack.size = 5; mloop_evsock_send(&mloop, &pack); } - diff --git a/tizen/src/osutil-darwin.c b/tizen/src/osutil-darwin.c index 75978b5a74..66ef616aca 100644 --- a/tizen/src/osutil-darwin.c +++ b/tizen/src/osutil-darwin.c @@ -49,9 +49,11 @@ #include #include #include +#include MULTI_DEBUG_CHANNEL(qemu, osutil); +int g_shmid; extern char tizen_target_img_path[]; extern int tizen_base_port; CFDictionaryRef proxySettings; @@ -85,23 +87,22 @@ void check_vm_lock_os(void) void make_vm_lock_os(void) { - int shmid; char *shared_memory; - shmid = shmget((key_t)tizen_base_port, MAXLEN, 0666|IPC_CREAT); - if (shmid == -1) { + g_shmid = shmget((key_t)tizen_base_port, MAXLEN, 0666|IPC_CREAT); + if (g_shmid == -1) { ERR("shmget failed\n"); perror("osutil-darwin: "); return; } - shared_memory = shmat(shmid, (char *)0x00, 0); + shared_memory = shmat(g_shmid, (char *)0x00, 0); if (shared_memory == (void *)-1) { ERR("shmat failed\n"); perror("osutil-darwin: "); return; } - sprintf(shared_memory, "%s", tizen_target_img_path); + g_sprintf(shared_memory, "%s", tizen_target_img_path); INFO("shared memory key: %d, value: %s\n", tizen_base_port, (char *)shared_memory); if (shmdt(shared_memory) == -1) { @@ -137,10 +138,42 @@ void set_bin_path_os(gchar * exec_argv) free(data); } +int get_number_of_processors(void) +{ + int mib[2], sys_num = 0; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_AVAILCPU; + + sysctl(mib, 2, &sys_num, &len, NULL, 0); + if (sys_num < 1) { + mib[1] = HW_NCPU; + sysctl(mib, 2, &sys_num, &len, NULL, 0); + + if (sys_num < 1) { + sys_num = 1; + } + } + INFO("* Number of processors : %d\n", sys_num); + + return sys_num; +} + +static void get_host_os_version(void) +{ + int major_version, minor_version, bugfix_version; + + Gestalt(gestaltSystemVersionMajor, &major_version); + Gestalt(gestaltSystemVersionMinor, &minor_version); + Gestalt(gestaltSystemVersionBugFix, &bugfix_version); + + INFO("* Mac OS X Version: %d.%d.%d\n", major_version, minor_version, bugfix_version); +} void print_system_info_os(void) { - INFO("* Mac\n"); + INFO("* Mac\n"); /* uname */ INFO("* Host machine uname :\n"); @@ -175,12 +208,15 @@ void print_system_info_os(void) } free(sys_info); +#if 0 mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(sys_num); if (sysctl(mib, 2, &sys_num, &len, NULL, 0) >= 0) { INFO("* Number of processors : %d\n", sys_num); } +#endif + get_number_of_processors(); mib[0] = CTL_HW; mib[1] = HW_PHYSMEM; @@ -188,6 +224,8 @@ void print_system_info_os(void) if (sysctl(mib, 2, &sys_num, &len, NULL, 0) >= 0) { INFO("* Total memory : %llu bytes\n", sys_num); } + + get_host_os_version(); } static int get_auto_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) @@ -241,7 +279,7 @@ static int get_auto_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, } else { ERR("fail to get pacfile fp\n"); - return -1; + return -1; } remove(pac_tempfile); @@ -333,7 +371,7 @@ void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, cha ret = get_auto_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); if(strlen(http_proxy) == 0 && ret < 0) { INFO("MANUAL PROXY MODE\n"); - get_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); - } + get_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + } } } diff --git a/tizen/src/osutil-linux.c b/tizen/src/osutil-linux.c index a821b7c6c8..886f89f5a3 100644 --- a/tizen/src/osutil-linux.c +++ b/tizen/src/osutil-linux.c @@ -1,9 +1,9 @@ -/* +/* * Emulator * * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved. * - * Contact: + * Contact: * SeokYeon Hwang * MunKyu Im * GiWoong Kim @@ -63,16 +63,16 @@ int gproxytool = GCONFTOOL; /* Getting proxy commands */ static const char* gproxycmds[][2] = { - { "gconftool-2 -g /system/proxy/mode" , "gsettings get org.gnome.system.proxy mode" }, - { "gconftool-2 -g /system/proxy/autoconfig_url", "gsettings get org.gnome.system.proxy autoconfig-url" }, - { "gconftool-2 -g /system/http_proxy/host", "gsettings get org.gnome.system.proxy.http host" }, - { "gconftool-2 -g /system/http_proxy/port", "gsettings get org.gnome.system.proxy.http port"}, - { "gconftool-2 -g /system/proxy/secure_host", "gsettings get org.gnome.system.proxy.https host" }, - { "gconftool-2 -g /system/proxy/secure_port", "gsettings get org.gnome.system.proxy.https port" }, - { "gconftool-2 -g /system/proxy/ftp_host", "gsettings get org.gnome.system.proxy.ftp host" }, - { "gconftool-2 -g /system/proxy/ftp_port", "gsettings get org.gnome.system.proxy.ftp port" }, - { "gconftool-2 -g /system/proxy/socks_host", "gsettings get org.gnome.system.proxy.socks host" }, - { "gconftool-2 -g /system/proxy/socks_port", "gsettings get org.gnome.system.proxy.socks port" }, + { "gconftool-2 -g /system/proxy/mode" , "gsettings get org.gnome.system.proxy mode" }, + { "gconftool-2 -g /system/proxy/autoconfig_url", "gsettings get org.gnome.system.proxy autoconfig-url" }, + { "gconftool-2 -g /system/http_proxy/host", "gsettings get org.gnome.system.proxy.http host" }, + { "gconftool-2 -g /system/http_proxy/port", "gsettings get org.gnome.system.proxy.http port"}, + { "gconftool-2 -g /system/proxy/secure_host", "gsettings get org.gnome.system.proxy.https host" }, + { "gconftool-2 -g /system/proxy/secure_port", "gsettings get org.gnome.system.proxy.https port" }, + { "gconftool-2 -g /system/proxy/ftp_host", "gsettings get org.gnome.system.proxy.ftp host" }, + { "gconftool-2 -g /system/proxy/ftp_port", "gsettings get org.gnome.system.proxy.ftp port" }, + { "gconftool-2 -g /system/proxy/socks_host", "gsettings get org.gnome.system.proxy.socks host" }, + { "gconftool-2 -g /system/proxy/socks_port", "gsettings get org.gnome.system.proxy.socks port" }, }; void check_vm_lock_os(void) @@ -161,15 +161,28 @@ void set_bin_path_os(gchar * exec_argv) g_strlcat(bin_path, "/", PATH_MAX); } +int get_number_of_processors(void) +{ + int num_processors = 0; + + num_processors = sysconf(_SC_NPROCESSORS_ONLN); + if (num_processors < 1) { + num_processors = 1; + } + TRACE("Number of processors : %d\n", num_processors); + + return num_processors; +} + void print_system_info_os(void) { INFO("* Linux\n"); /* depends on building */ INFO("* QEMU build machine linux kernel version : (%d, %d, %d)\n", - LINUX_VERSION_CODE >> 16, - (LINUX_VERSION_CODE >> 8) & 0xff, - LINUX_VERSION_CODE & 0xff); + LINUX_VERSION_CODE >> 16, + (LINUX_VERSION_CODE >> 8) & 0xff, + LINUX_VERSION_CODE & 0xff); /* depends on launching */ struct utsname host_uname_buf; diff --git a/tizen/src/osutil-win32.c b/tizen/src/osutil-win32.c index ad5ef1046a..2acbfef85c 100644 --- a/tizen/src/osutil-win32.c +++ b/tizen/src/osutil-win32.c @@ -1,9 +1,9 @@ -/* +/* * Emulator * * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved. * - * Contact: + * Contact: * SeokYeon Hwang * MunKyu Im * GiWoong Kim @@ -140,6 +140,23 @@ void set_bin_path_os(gchar * exec_argv) g_strlcat(bin_path, "\\", PATH_MAX); } +int get_number_of_processors(void) +{ + SYSTEM_INFO sysi; + int num_processors = 0; + + GetSystemInfo(&sysi); + TRACE("Processor type: %d, Core number: %d\n", + sysi.dwProcessorType, sysi.dwNumberOfProcessors); + + num_processors = sysi.dwNumberOfProcessors; + if (num_processors < 1) { + num_processors = 1; + } + + return num_processors; +} + void print_system_info_os(void) { INFO("* Windows\n"); @@ -160,9 +177,12 @@ void print_system_info_os(void) SYSTEM_INFO sysi; ZeroMemory(&sysi, sizeof(SYSTEM_INFO)); +#if 0 GetSystemInfo(&sysi); INFO("* Processor type : %d, Number of processors : %d\n", sysi.dwProcessorType, sysi.dwNumberOfProcessors); +#endif + get_number_of_processors(); MEMORYSTATUSEX memInfo; memInfo.dwLength = sizeof(MEMORYSTATUSEX); @@ -213,7 +233,7 @@ static int get_auto_proxy(BYTE *url, char *http_proxy, char *https_proxy, char * ERR("pac file is not wrong! It could be the wrong pac address or pac file format\n"); fclose(fp_pacfile); } - } + } else { ERR("fail to get pacfile fp\n"); return -1; @@ -260,7 +280,7 @@ void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, cha lRet = RegQueryValueEx(hKey, "AutoConfigURL", 0, NULL, url, &dwLength); if (lRet == ERROR_SUCCESS && dwLength != 0) { get_auto_proxy(url, http_proxy, https_proxy, ftp_proxy, socks_proxy); - RegCloseKey(hKey); + RegCloseKey(hKey); return 0; } } @@ -290,7 +310,7 @@ void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, cha } if (*(char*)proxyenable == 0) { free(proxyenable); - RegCloseKey(hKey); + RegCloseKey(hKey); return 0; } @@ -299,14 +319,14 @@ void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, cha if (lRet != ERROR_SUCCESS && dwLength == 0) { ERR("Failed to query value from from %s\n", "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); - RegCloseKey(hKey); + RegCloseKey(hKey); return 0; } proxyserver = (BYTE*)malloc(dwLength); if (proxyserver == NULL) { ERR( "Failed to allocate a buffer\n"); - RegCloseKey(hKey); + RegCloseKey(hKey); return 0; } @@ -319,11 +339,11 @@ void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, cha RegCloseKey(hKey); return 0; } - + if((char*)proxyserver != NULL) { INFO("proxy value: %s\n", (char*)proxyserver); real_proxy = malloc(MAXLEN); - + for(p = strtok((char*)proxyserver, ";"); p; p = strtok(NULL, ";")){ if(strstr(p, HTTP_PROTOCOL)) { remove_string(p, real_proxy, HTTP_PROTOCOL); diff --git a/tizen/src/osutil.h b/tizen/src/osutil.h index 29524c872f..bc4f890c81 100644 --- a/tizen/src/osutil.h +++ b/tizen/src/osutil.h @@ -71,5 +71,7 @@ inline void download_url(char *); inline size_t write_data(void *, size_t, size_t, FILE *); inline void remove_string(char *, char *, const char *); +int get_number_of_processors(void); + #endif // __OS_UTIL_H__ diff --git a/tizen/src/skin/client/.project b/tizen/src/skin/client/.project deleted file mode 100644 index cdb4a9e099..0000000000 --- a/tizen/src/skin/client/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - EmulatorSkin - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/tizen/src/skin/client/skins/emul-320x480/default.dbi b/tizen/src/skin/client/skins/emul-320x480-1btn/default.dbi similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default.dbi rename to tizen/src/skin/client/skins/emul-320x480-1btn/default.dbi diff --git a/tizen/src/skin/client/skins/emul-320x480/default_0.png b/tizen/src/skin/client/skins/emul-320x480-1btn/default_0.png similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default_0.png rename to tizen/src/skin/client/skins/emul-320x480-1btn/default_0.png diff --git a/tizen/src/skin/client/skins/emul-320x480/default_0_p.png b/tizen/src/skin/client/skins/emul-320x480-1btn/default_0_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default_0_p.png rename to tizen/src/skin/client/skins/emul-320x480-1btn/default_0_p.png diff --git a/tizen/src/skin/client/skins/emul-320x480/default_180.png b/tizen/src/skin/client/skins/emul-320x480-1btn/default_180.png similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default_180.png rename to tizen/src/skin/client/skins/emul-320x480-1btn/default_180.png diff --git a/tizen/src/skin/client/skins/emul-320x480/default_180_p.png b/tizen/src/skin/client/skins/emul-320x480-1btn/default_180_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default_180_p.png rename to tizen/src/skin/client/skins/emul-320x480-1btn/default_180_p.png diff --git a/tizen/src/skin/client/skins/emul-320x480/default_L90.png b/tizen/src/skin/client/skins/emul-320x480-1btn/default_L90.png similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default_L90.png rename to tizen/src/skin/client/skins/emul-320x480-1btn/default_L90.png diff --git a/tizen/src/skin/client/skins/emul-320x480/default_L90_p.png b/tizen/src/skin/client/skins/emul-320x480-1btn/default_L90_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default_L90_p.png rename to tizen/src/skin/client/skins/emul-320x480-1btn/default_L90_p.png diff --git a/tizen/src/skin/client/skins/emul-320x480/default_R90.png b/tizen/src/skin/client/skins/emul-320x480-1btn/default_R90.png similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default_R90.png rename to tizen/src/skin/client/skins/emul-320x480-1btn/default_R90.png diff --git a/tizen/src/skin/client/skins/emul-320x480/default_R90_p.png b/tizen/src/skin/client/skins/emul-320x480-1btn/default_R90_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/default_R90_p.png rename to tizen/src/skin/client/skins/emul-320x480-1btn/default_R90_p.png diff --git a/tizen/src/skin/client/skins/emul-320x480/info.ini b/tizen/src/skin/client/skins/emul-320x480-1btn/info.ini similarity index 100% rename from tizen/src/skin/client/skins/emul-320x480/info.ini rename to tizen/src/skin/client/skins/emul-320x480-1btn/info.ini diff --git a/tizen/src/skin/client/skins/emul-480x800/default.dbi b/tizen/src/skin/client/skins/emul-480x800-1btn/default.dbi similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default.dbi rename to tizen/src/skin/client/skins/emul-480x800-1btn/default.dbi diff --git a/tizen/src/skin/client/skins/emul-480x800/default_0.png b/tizen/src/skin/client/skins/emul-480x800-1btn/default_0.png similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default_0.png rename to tizen/src/skin/client/skins/emul-480x800-1btn/default_0.png diff --git a/tizen/src/skin/client/skins/emul-480x800/default_0_p.png b/tizen/src/skin/client/skins/emul-480x800-1btn/default_0_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default_0_p.png rename to tizen/src/skin/client/skins/emul-480x800-1btn/default_0_p.png diff --git a/tizen/src/skin/client/skins/emul-480x800/default_180.png b/tizen/src/skin/client/skins/emul-480x800-1btn/default_180.png similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default_180.png rename to tizen/src/skin/client/skins/emul-480x800-1btn/default_180.png diff --git a/tizen/src/skin/client/skins/emul-480x800/default_180_p.png b/tizen/src/skin/client/skins/emul-480x800-1btn/default_180_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default_180_p.png rename to tizen/src/skin/client/skins/emul-480x800-1btn/default_180_p.png diff --git a/tizen/src/skin/client/skins/emul-480x800/default_L90.png b/tizen/src/skin/client/skins/emul-480x800-1btn/default_L90.png similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default_L90.png rename to tizen/src/skin/client/skins/emul-480x800-1btn/default_L90.png diff --git a/tizen/src/skin/client/skins/emul-480x800/default_L90_p.png b/tizen/src/skin/client/skins/emul-480x800-1btn/default_L90_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default_L90_p.png rename to tizen/src/skin/client/skins/emul-480x800-1btn/default_L90_p.png diff --git a/tizen/src/skin/client/skins/emul-480x800/default_R90.png b/tizen/src/skin/client/skins/emul-480x800-1btn/default_R90.png similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default_R90.png rename to tizen/src/skin/client/skins/emul-480x800-1btn/default_R90.png diff --git a/tizen/src/skin/client/skins/emul-480x800/default_R90_p.png b/tizen/src/skin/client/skins/emul-480x800-1btn/default_R90_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/default_R90_p.png rename to tizen/src/skin/client/skins/emul-480x800-1btn/default_R90_p.png diff --git a/tizen/src/skin/client/skins/emul-480x800/info.ini.bak b/tizen/src/skin/client/skins/emul-480x800-1btn/info.ini.bak similarity index 100% rename from tizen/src/skin/client/skins/emul-480x800/info.ini.bak rename to tizen/src/skin/client/skins/emul-480x800-1btn/info.ini.bak diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default.dbi b/tizen/src/skin/client/skins/emul-540x960-3btn/default.dbi new file mode 100644 index 0000000000..b78b2846e5 --- /dev/null +++ b/tizen/src/skin/client/skins/emul-540x960-3btn/default.dbi @@ -0,0 +1,245 @@ + + + + + + + + + + default_0.png + default_0_p.png + + + + + + 169 + Menu + + Menu + + + + + 139 + Home + + Home + + + + + 158 + Back + + Back + + + + + 116 + Power + + Power + + + + + 115 + Volume + + + Volume + + + + + + 114 + Volume - + + Volume - + + + + + + + + + default_L90.png + default_L90_p.png + + + + + + 169 + Menu + + Menu + + + + + 139 + Home + + Home + + + + + 158 + Back + + Back + + + + + 116 + Power + + Power + + + + + 115 + Volume + + + Volume + + + + + + 114 + Volume - + + Volume - + + + + + + + + + default_180.png + default_180_p.png + + + + + + 169 + Menu + + Menu + + + + + 139 + Home + + Home + + + + + 158 + Back + + Back + + + + + 116 + Power + + Power + + + + + 115 + Volume + + + Volume + + + + + + 114 + Volume - + + Volume - + + + + + + + + + default_R90.png + default_R90_p.png + + + + + + 169 + Menu + + Menu + + + + + 139 + Home + + Home + + + + + 158 + Back + + Back + + + + + 116 + Power + + Power + + + + + 115 + Volume + + + Volume + + + + + + 114 + Volume - + + Volume - + + + + + + + + diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default_0.png b/tizen/src/skin/client/skins/emul-540x960-3btn/default_0.png new file mode 100644 index 0000000000000000000000000000000000000000..a9872a33ebffdf3b39b5e6f65f678f64c0381e6f GIT binary patch literal 56734 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 literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default_0_p.png b/tizen/src/skin/client/skins/emul-540x960-3btn/default_0_p.png new file mode 100644 index 0000000000000000000000000000000000000000..09d7468ddc2325021ed0a5ab1110623b77a1517b GIT binary patch literal 62762 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 bYkVAyDYnwPCB&6D;7?6S^Ktn@v*7;#D5etR literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default_180.png b/tizen/src/skin/client/skins/emul-540x960-3btn/default_180.png new file mode 100644 index 0000000000000000000000000000000000000000..f73a6ef671f5626b702efffdf6e42afb9dc4bcc9 GIT binary patch literal 57165 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 literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default_180_p.png b/tizen/src/skin/client/skins/emul-540x960-3btn/default_180_p.png new file mode 100644 index 0000000000000000000000000000000000000000..aa509b72d81e41659aa06be29db91676dd5cd2f0 GIT binary patch literal 63582 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�S3RP0Mul;MLC#Noaivo$E^CKbsUUT;u!M^v$P) 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 C4bPtd literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default_L90.png b/tizen/src/skin/client/skins/emul-540x960-3btn/default_L90.png new file mode 100644 index 0000000000000000000000000000000000000000..d9936e1fa58cd0be708cee73f6e79175268ae1c3 GIT binary patch literal 53190 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 QMgHfV+p6-pvU)!M9}5KkfdBvi literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default_L90_p.png b/tizen/src/skin/client/skins/emul-540x960-3btn/default_L90_p.png new file mode 100644 index 0000000000000000000000000000000000000000..472705330c74650e790c75b51e62bb80c1ac313e GIT binary patch literal 59676 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 literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default_R90.png b/tizen/src/skin/client/skins/emul-540x960-3btn/default_R90.png new file mode 100644 index 0000000000000000000000000000000000000000..61703dc7b5b258221aca72da1518c3133dca08b5 GIT binary patch literal 52643 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 literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/default_R90_p.png b/tizen/src/skin/client/skins/emul-540x960-3btn/default_R90_p.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaeeebc47a4995ec698cbfb88f4378f4de9f018 GIT binary patch literal 59677 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%0Aeo?+8M7IQin1X=4ovw11;_ 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 %Jpwdv% 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 literal 0 HcmV?d00001 diff --git a/tizen/src/skin/client/skins/emul-540x960-3btn/info.ini b/tizen/src/skin/client/skins/emul-540x960-3btn/info.ini new file mode 100644 index 0000000000..7667a861b6 --- /dev/null +++ b/tizen/src/skin/client/skins/emul-540x960-3btn/info.ini @@ -0,0 +1,4 @@ +skin.name=Phone 540x960 +resolution.width=540 +resolution.height=960 +manager.priority=4 diff --git a/tizen/src/skin/client/skins/emul-600x1024/default.dbi b/tizen/src/skin/client/skins/emul-600x1024-1btn/default.dbi similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default.dbi rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default.dbi diff --git a/tizen/src/skin/client/skins/emul-600x1024/default_0.png b/tizen/src/skin/client/skins/emul-600x1024-1btn/default_0.png similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default_0.png rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default_0.png diff --git a/tizen/src/skin/client/skins/emul-600x1024/default_0_p.png b/tizen/src/skin/client/skins/emul-600x1024-1btn/default_0_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default_0_p.png rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default_0_p.png diff --git a/tizen/src/skin/client/skins/emul-600x1024/default_180.png b/tizen/src/skin/client/skins/emul-600x1024-1btn/default_180.png similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default_180.png rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default_180.png diff --git a/tizen/src/skin/client/skins/emul-600x1024/default_180_p.png b/tizen/src/skin/client/skins/emul-600x1024-1btn/default_180_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default_180_p.png rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default_180_p.png diff --git a/tizen/src/skin/client/skins/emul-600x1024/default_L90.png b/tizen/src/skin/client/skins/emul-600x1024-1btn/default_L90.png similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default_L90.png rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default_L90.png diff --git a/tizen/src/skin/client/skins/emul-600x1024/default_L90_p.png b/tizen/src/skin/client/skins/emul-600x1024-1btn/default_L90_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default_L90_p.png rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default_L90_p.png diff --git a/tizen/src/skin/client/skins/emul-600x1024/default_R90.png b/tizen/src/skin/client/skins/emul-600x1024-1btn/default_R90.png similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default_R90.png rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default_R90.png diff --git a/tizen/src/skin/client/skins/emul-600x1024/default_R90_p.png b/tizen/src/skin/client/skins/emul-600x1024-1btn/default_R90_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/default_R90_p.png rename to tizen/src/skin/client/skins/emul-600x1024-1btn/default_R90_p.png diff --git a/tizen/src/skin/client/skins/emul-600x1024/info.ini b/tizen/src/skin/client/skins/emul-600x1024-1btn/info.ini similarity index 100% rename from tizen/src/skin/client/skins/emul-600x1024/info.ini rename to tizen/src/skin/client/skins/emul-600x1024-1btn/info.ini diff --git a/tizen/src/skin/client/skins/emul-720x1280/default.dbi b/tizen/src/skin/client/skins/emul-720x1280-1btn/default.dbi similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default.dbi rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default.dbi diff --git a/tizen/src/skin/client/skins/emul-720x1280/default_0.png b/tizen/src/skin/client/skins/emul-720x1280-1btn/default_0.png similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default_0.png rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default_0.png diff --git a/tizen/src/skin/client/skins/emul-720x1280/default_0_p.png b/tizen/src/skin/client/skins/emul-720x1280-1btn/default_0_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default_0_p.png rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default_0_p.png diff --git a/tizen/src/skin/client/skins/emul-720x1280/default_180.png b/tizen/src/skin/client/skins/emul-720x1280-1btn/default_180.png similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default_180.png rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default_180.png diff --git a/tizen/src/skin/client/skins/emul-720x1280/default_180_p.png b/tizen/src/skin/client/skins/emul-720x1280-1btn/default_180_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default_180_p.png rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default_180_p.png diff --git a/tizen/src/skin/client/skins/emul-720x1280/default_L90.png b/tizen/src/skin/client/skins/emul-720x1280-1btn/default_L90.png similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default_L90.png rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default_L90.png diff --git a/tizen/src/skin/client/skins/emul-720x1280/default_L90_p.png b/tizen/src/skin/client/skins/emul-720x1280-1btn/default_L90_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default_L90_p.png rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default_L90_p.png diff --git a/tizen/src/skin/client/skins/emul-720x1280/default_R90.png b/tizen/src/skin/client/skins/emul-720x1280-1btn/default_R90.png similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default_R90.png rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default_R90.png diff --git a/tizen/src/skin/client/skins/emul-720x1280/default_R90_p.png b/tizen/src/skin/client/skins/emul-720x1280-1btn/default_R90_p.png similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/default_R90_p.png rename to tizen/src/skin/client/skins/emul-720x1280-1btn/default_R90_p.png diff --git a/tizen/src/skin/client/skins/emul-720x1280/info.ini.bak b/tizen/src/skin/client/skins/emul-720x1280-1btn/info.ini.bak similarity index 100% rename from tizen/src/skin/client/skins/emul-720x1280/info.ini.bak rename to tizen/src/skin/client/skins/emul-720x1280-1btn/info.ini.bak diff --git a/tizen/src/skin/client/skins/emul-general/default.dbi b/tizen/src/skin/client/skins/emul-general/default.dbi deleted file mode 100644 index 82cee6484f..0000000000 --- a/tizen/src/skin/client/skins/emul-general/default.dbi +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - 139 - Home - - Home - - - - 116 - Power - - Power - - - - 115 - Volume + - - Volume + - - - - 114 - Volume - - - Volume - - - - - - - - - - - - - - - - - - - - - diff --git a/tizen/src/skin/client/skins/emul-general/info.ini.bak b/tizen/src/skin/client/skins/emul-general/info.ini.bak deleted file mode 100644 index 1823020106..0000000000 --- a/tizen/src/skin/client/skins/emul-general/info.ini.bak +++ /dev/null @@ -1,4 +0,0 @@ -skin.name=General purpose 1btn -resolution.width=all -resolution.height=all -manager.priority=0 diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java index ccc6c90837..358e71e924 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorFingers.java @@ -1,5 +1,5 @@ /** - * + * Multi-touch * * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. * @@ -486,9 +486,9 @@ public class EmulatorFingers { } } - if (count != 0) { + /* if (count != 0) { this.grabFingerID = 0; - } + } */ return count; } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSdlSkin.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSdlSkin.java index 149137ca02..26cac214ae 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSdlSkin.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSdlSkin.java @@ -33,6 +33,9 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.eclipse.swt.SWT; +import org.tizen.emulator.skin.comm.ICommunicator.MouseEventType; +import org.tizen.emulator.skin.comm.ICommunicator.SendCommand; +import org.tizen.emulator.skin.comm.sock.data.MouseEventData; import org.tizen.emulator.skin.config.EmulatorConfig; import org.tizen.emulator.skin.exception.ScreenShotException; import org.tizen.emulator.skin.image.ImageRegistry.IconName; @@ -127,7 +130,15 @@ public class EmulatorSdlSkin extends EmulatorSkin { @Override public void displayOff() { logger.info("display off"); - /* do nothing */ + + if (isDisplayDragging == true) { + logger.info("auto release : mouseEvent"); + MouseEventData mouseEventData = new MouseEventData( + 0, MouseEventType.RELEASE.value(), + 0, 0, 0, 0, 0); + + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + } } @Override diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java index b6562cfb89..c5aaa2fae8 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorShmSkin.java @@ -39,6 +39,9 @@ import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.Transform; import org.eclipse.swt.widgets.Display; +import org.tizen.emulator.skin.comm.ICommunicator.MouseEventType; +import org.tizen.emulator.skin.comm.ICommunicator.SendCommand; +import org.tizen.emulator.skin.comm.sock.data.MouseEventData; import org.tizen.emulator.skin.config.EmulatorConfig; import org.tizen.emulator.skin.config.EmulatorConfig.ArgsConstants; import org.tizen.emulator.skin.exception.ScreenShotException; @@ -111,7 +114,6 @@ public class EmulatorShmSkin extends EmulatorSkin { public void run() { stopRequest = false; - Image temp; int sizeFramebuffer = widthFB * heightFB; while (!stopRequest) { @@ -294,6 +296,15 @@ public class EmulatorShmSkin extends EmulatorSkin { public void displayOff() { logger.info("display off"); + if (isDisplayDragging == true) { + logger.info("auto release : mouseEvent"); + MouseEventData mouseEventData = new MouseEventData( + 0, MouseEventType.RELEASE.value(), + 0, 0, 0, 0, 0); + + communicator.sendToQEMU(SendCommand.SEND_MOUSE_EVENT, mouseEventData); + } + if (pollThread.isAlive()) { pollThread.setWaitIntervalTime(0); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java index 8eb94a1f59..853d27010b 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java @@ -92,7 +92,7 @@ import org.tizen.emulator.skin.image.ImageRegistry.IconName; import org.tizen.emulator.skin.info.SkinInformation; import org.tizen.emulator.skin.layout.GeneralPurposeSkinComposer; import org.tizen.emulator.skin.layout.ISkinComposer; -import org.tizen.emulator.skin.layout.PhoneShapeSkinComposer; +import org.tizen.emulator.skin.layout.ProfileSpecificSkinComposer; import org.tizen.emulator.skin.log.SkinLogger; import org.tizen.emulator.skin.screenshot.ScreenShotDialog; import org.tizen.emulator.skin.util.SkinRotation; @@ -110,7 +110,7 @@ public class EmulatorSkin { private EmulatorSkin reopenSkin; private boolean reopen; - private SkinReopenPolicy( EmulatorSkin reopenSkin, boolean reopen ) { + private SkinReopenPolicy(EmulatorSkin reopenSkin, boolean reopen) { this.reopenSkin = reopenSkin; this.reopen = reopen; } @@ -122,7 +122,6 @@ public class EmulatorSkin { public boolean isReopen() { return reopen; } - } public enum SkinBasicColor { @@ -166,7 +165,8 @@ public class EmulatorSkin { protected EmulatorSkinState currentState; - private boolean isDragStartedInLCD; + protected boolean isDisplayDragging; + protected Point shellGrabPosition; private boolean isShutdownRequested; private boolean isAboutToReopen; private boolean isOnTop; @@ -232,6 +232,8 @@ public class EmulatorSkin { SkinUtil.setTopMost(shell, true); } + this.shellGrabPosition = new Point(-1, -1); + this.displayCanvasStyle = displayCanvasStyle; /* generate a pair tag color of key window */ @@ -265,10 +267,10 @@ public class EmulatorSkin { imageRegistry = ImageRegistry.getInstance(); if (skinInfo.isPhoneShape() == true) { /* phone shape skin */ - skinComposer = new PhoneShapeSkinComposer(config, this, + skinComposer = new ProfileSpecificSkinComposer(config, this, shell, currentState, imageRegistry, communicator); - ((PhoneShapeSkinComposer) skinComposer).addPhoneShapeListener(shell); + ((ProfileSpecificSkinComposer) skinComposer).addPhoneShapeListener(shell); } else { /* general purpose skin */ skinComposer = new GeneralPurposeSkinComposer(config, this, shell, currentState, imageRegistry); @@ -398,9 +400,34 @@ public class EmulatorSkin { } protected void skinFinalize() { + logger.info("skinFinalize"); + skinComposer.composerFinalize(); } + /* window grabbing */ + public void grabShell(int x, int y) { + shellGrabPosition.x = x; + shellGrabPosition.y = y; + } + + public void ungrabShell() { + shellGrabPosition.x = -1; + shellGrabPosition.y = -1; + } + + public boolean isShellGrabbing() { + return shellGrabPosition.x >= 0 && shellGrabPosition.y >= 0; + } + + public Point getGrabPosition() { + if (isShellGrabbing() == false) { + return null; + } + + return shellGrabPosition; + } + private void addMainWindowListener(final Shell shell) { shellListener = new ShellListener() { @@ -547,7 +574,16 @@ public class EmulatorSkin { shellMenuDetectListener = new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { - Menu menu = EmulatorSkin.this.contextMenu; + if (isDisplayDragging == true || isShellGrabbing() == true + || isShutdownRequested == true) { + logger.info("menu is blocked"); + + e.doit = false; + return; + } + + Menu menu = contextMenu; + keyForceRelease(true); if (menu != null) { shell.setMenu(menu); @@ -578,12 +614,21 @@ public class EmulatorSkin { canvasMenuDetectListener = new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { - Menu menu = EmulatorSkin.this.contextMenu; + if (isDisplayDragging == true || isShellGrabbing() == true + || isShutdownRequested == true) { + logger.info("menu is blocked"); + + e.doit = false; + return; + } + + Menu menu = contextMenu; keyForceRelease(true); - if (menu != null && EmulatorSkin.this.isDragStartedInLCD == false) { + if (menu != null) { lcdCanvas.setMenu(menu); menu.setVisible(true); + e.doit = false; } else { lcdCanvas.setMenu(null); @@ -638,28 +683,28 @@ public class EmulatorSkin { @Override public void mouseMove( MouseEvent e ) { - if ( true == EmulatorSkin.this.isDragStartedInLCD ) { //true = mouse down + if (true == isDisplayDragging) { //true = mouse down int eventType = MouseEventType.DRAG.value(); Point canvasSize = canvas.getSize(); if ( e.x < 0 ) { e.x = 0; eventType = MouseEventType.RELEASE.value(); - EmulatorSkin.this.isDragStartedInLCD = false; + isDisplayDragging = false; } else if ( e.x >= canvasSize.x ) { e.x = canvasSize.x - 1; eventType = MouseEventType.RELEASE.value(); - EmulatorSkin.this.isDragStartedInLCD = false; + isDisplayDragging = false; } if ( e.y < 0 ) { e.y = 0; eventType = MouseEventType.RELEASE.value(); - EmulatorSkin.this.isDragStartedInLCD = false; + isDisplayDragging = false; } else if ( e.y >= canvasSize.y ) { e.y = canvasSize.y - 1; eventType = MouseEventType.RELEASE.value(); - EmulatorSkin.this.isDragStartedInLCD = false; + isDisplayDragging = false; } int[] geometry = SkinUtil.convertMouseGeometry(e.x, e.y, @@ -705,8 +750,8 @@ public class EmulatorSkin { logger.info("mouseUp in display" + " x:" + geometry[0] + " y:" + geometry[1]); - if (true == EmulatorSkin.this.isDragStartedInLCD) { - EmulatorSkin.this.isDragStartedInLCD = false; + if (true == isDisplayDragging) { + isDisplayDragging = false; } if (SwtUtil.isMacPlatform()) { @@ -747,8 +792,8 @@ public class EmulatorSkin { logger.info("mouseDown in display" + " x:" + geometry[0] + " y:" + geometry[1]); - if (false == EmulatorSkin.this.isDragStartedInLCD) { - EmulatorSkin.this.isDragStartedInLCD = true; + if (false == isDisplayDragging) { + isDisplayDragging = true; } if (SwtUtil.isMacPlatform()) { @@ -827,8 +872,16 @@ public class EmulatorSkin { @Override public void keyReleased(KeyEvent e) { if (logger.isLoggable(Level.INFO)) { - logger.info("'" + e.character + "':" + - e.keyCode + ":" + e.stateMask + ":" + e.keyLocation); + String character = + (e.character == '\0') ? "\\0" : + (e.character == '\n') ? "\\n" : + (e.character == '\r') ? "\\r" : + ("" + e.character); + + logger.info("'" + character + "':" + + e.keyCode + ":" + + e.stateMask + ":" + + e.keyLocation); } else if (logger.isLoggable(Level.FINE)) { logger.fine(e.toString()); } @@ -836,26 +889,72 @@ public class EmulatorSkin { int keyCode = e.keyCode; int stateMask = e.stateMask; - previous = null; + if (SwtUtil.isWindowsPlatform() == true) { + if (disappearEvent == true) { + /* generate a disappeared key event in Windows */ + disappearEvent = false; - /* generate a disappeared key event in Windows */ - if (SwtUtil.isWindowsPlatform() && disappearEvent) { - disappearEvent = false; - if (isMetaKey(e.keyCode) && e.character != '\0') { - logger.info("send disappear release : keycode=" + disappearKeycode + - ", stateMask=" + disappearStateMask + - ", keyLocation=" + disappearKeyLocation); + if (isMetaKey(e.keyCode) && e.character != '\0') { + logger.info("send disappear release : keycode=" + disappearKeycode + + ", stateMask=" + disappearStateMask + + ", keyLocation=" + disappearKeyLocation); - KeyEventData keyEventData = new KeyEventData( - KeyEventType.RELEASED.value(), - disappearKeycode, disappearStateMask, disappearKeyLocation); - communicator.sendToQEMU(SendCommand.SEND_KEY_EVENT, keyEventData); + KeyEventData keyEventData = new KeyEventData( + KeyEventType.RELEASED.value(), + disappearKeycode, disappearStateMask, disappearKeyLocation); + communicator.sendToQEMU(SendCommand.SEND_KEY_EVENT, keyEventData); - removePressedKey(keyEventData); + removePressedKey(keyEventData); - disappearKeycode = 0; - disappearStateMask = 0; - disappearKeyLocation = 0; + disappearKeycode = 0; + disappearStateMask = 0; + disappearKeyLocation = 0; + } + } + + if (previous != null) { + KeyEventData keyEventData = null; + + /* separate a merged release event */ + if (previous.keyCode == SWT.CR && + (keyCode & SWT.KEYCODE_BIT) != 0 && e.character == SWT.CR) { + logger.info("send upon release : keycode=" + (int)SWT.CR); + + keyEventData = new KeyEventData( + KeyEventType.RELEASED.value(), + SWT.CR, 0, 0); + } else if (previous.keyCode == SWT.SPACE && + (keyCode & SWT.KEYCODE_BIT) != 0 && + (e.character == SWT.SPACE)) { + logger.info("send upon release : keycode=" + (int)SWT.SPACE); + + keyEventData = new KeyEventData( + KeyEventType.RELEASED.value(), + SWT.SPACE, 0, 0); + } else if (previous.keyCode == SWT.TAB && + (keyCode & SWT.KEYCODE_BIT) != 0 && + (e.character == SWT.TAB)) { + logger.info("send upon release : keycode=" + (int)SWT.TAB); + + keyEventData = new KeyEventData( + KeyEventType.RELEASED.value(), + SWT.TAB, 0, 0); + } else if (previous.keyCode == SWT.KEYPAD_CR && + (keyCode & SWT.KEYCODE_BIT) != 0 && + (e.character == SWT.CR) && + (keyCode != SWT.KEYPAD_CR)) { + logger.info("send upon release : keycode=" + (int)SWT.KEYPAD_CR); + + keyEventData = new KeyEventData( + KeyEventType.RELEASED.value(), + SWT.KEYPAD_CR, 0, 2); + } + + if (keyEventData != null) { + communicator.sendToQEMU(SendCommand.SEND_KEY_EVENT, + keyEventData); + removePressedKey(keyEventData); + } } } else if (SwtUtil.isMacPlatform()) { @@ -871,8 +970,10 @@ public class EmulatorSkin { finger.clearFingerSlot(); logger.info("disable multi-touch"); } - } - } + } + } + + previous = null; KeyEventData keyEventData = new KeyEventData( KeyEventType.RELEASED.value(), keyCode, stateMask, e.keyLocation); @@ -971,8 +1072,16 @@ public class EmulatorSkin { previous = e; if (logger.isLoggable(Level.INFO)) { - logger.info("'" + e.character + "':" + - e.keyCode + ":" + e.stateMask + ":" + e.keyLocation); + String character = + (e.character == '\0') ? "\\0" : + (e.character == '\n') ? "\\n" : + (e.character == '\r') ? "\\r" : + ("" + e.character); + + logger.info("'" + character + "':" + + e.keyCode + ":" + + e.stateMask + ":" + + e.keyLocation); } else if (logger.isLoggable(Level.FINE)) { logger.fine(e.toString()); } @@ -1279,7 +1388,7 @@ public class EmulatorSkin { return; } - int portSdb = config.getArgInt(ArgsConstants.NET_BASE_PORT); + int portSdb = config.getArgInt(ArgsConstants.NET_BASE_PORT) + 1; ProcessBuilder procSdb = new ProcessBuilder(); @@ -1688,7 +1797,7 @@ public class EmulatorSkin { int answer = SkinUtil.openMessage(shell, null, "If you force stop an emulator, it may cause some problems.\n" + - "Are you sure you want to contiue?", + "Are you sure you want to continue?", SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL, config); if (answer == SWT.OK) { @@ -1703,6 +1812,7 @@ public class EmulatorSkin { } public void shutdown() { + logger.info("shutdown the skin process"); isShutdownRequested = true; @@ -1714,7 +1824,7 @@ public class EmulatorSkin { EmulatorSkin.this.shell.close(); } } - } ); + }); } } @@ -1724,6 +1834,10 @@ public class EmulatorSkin { } public void keyForceRelease(boolean isMetaFilter) { + if (isShutdownRequested == true) { + return; + } + /* key event compensation */ if (pressedKeyEventList.isEmpty() == false) { for (KeyEventData data : pressedKeyEventList) { @@ -1738,11 +1852,11 @@ public class EmulatorSkin { KeyEventType.RELEASED.value(), data.keycode, data.stateMask, data.keyLocation); communicator.sendToQEMU( - SendCommand.SEND_KEY_EVENT, keyEventData, false); + SendCommand.SEND_KEY_EVENT, keyEventData); - logger.info("auto release : keycode=" + keyEventData.keycode + - ", stateMask=" + keyEventData.stateMask + - ", keyLocation=" + keyEventData.keyLocation); + logger.info("auto release : keycode=" + keyEventData.keycode + + ", stateMask=" + keyEventData.stateMask + + ", keyLocation=" + keyEventData.keyLocation); } } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkinMain.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkinMain.java index 5ee55241fc..2043a060f3 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkinMain.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkinMain.java @@ -1,7 +1,7 @@ /** - * + * Emulator Skin Main * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -57,6 +57,7 @@ import org.tizen.emulator.skin.image.ImageRegistry; import org.tizen.emulator.skin.info.SkinInformation; import org.tizen.emulator.skin.log.SkinLogger; import org.tizen.emulator.skin.log.SkinLogger.SkinLogLevel; +import org.tizen.emulator.skin.util.CocoaUtil; import org.tizen.emulator.skin.util.IOUtil; import org.tizen.emulator.skin.util.JaxbUtil; import org.tizen.emulator.skin.util.SkinUtil; @@ -94,10 +95,17 @@ public class EmulatorSkinMain { */ public static void main(String[] args) { - if(SwtUtil.isMacPlatform()) { - //TODO: event handling of about dialog + /* make vm name and remove unused menu for macos-x */ + if (SwtUtil.isMacPlatform()) { System.setProperty("apple.laf.useScreenMenuBar", "true"); - System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Emulator"); + System.setProperty("com.apple.mrj.application.apple.menu.about.name", + "Emulator"); + Display display = Display.getDefault(); + display.syncExec(new Runnable() { + public void run() { + new CocoaUtil().removeTopMenuItems(); + } + }); } String simpleMsg = getSimpleMsg(args); @@ -129,14 +137,16 @@ public class EmulatorSkinMain { logger = SkinLogger.getSkinLogger(EmulatorSkinMain.class).getLogger(); logger.info("!!! Start Emualtor Skin !!!"); - logger.info("java.version: " + System.getProperty("java.version")); - logger.info("java vendor: " + System.getProperty("java.vendor")); - logger.info("vm version: " + System.getProperty("java.vm.version")); - logger.info("vm vendor: " + System.getProperty("java.vm.vendor")); - logger.info("vm name: " + System.getProperty("java.vm.name")); - logger.info("os name: " + System.getProperty("os.name")); - logger.info("os arch: " + System.getProperty("os.arch")); - logger.info("os version: " + System.getProperty("os.version")); + logger.info("java.version : " + System.getProperty("java.version")); + logger.info("java vendor : " + System.getProperty("java.vendor")); + logger.info("vm version : " + System.getProperty("java.vm.version")); + logger.info("vm vendor : " + System.getProperty("java.vm.vendor")); + logger.info("vm name : " + System.getProperty("java.vm.name")); + logger.info("os name : " + System.getProperty("os.name")); + logger.info("os arch : " + System.getProperty("os.arch")); + logger.info("os version : " + System.getProperty("os.version")); + logger.info("swt platform : " + SWT.getPlatform()); + logger.info("swt version : " + SWT.getVersion()); /* startup arguments parsing */ Map argsMap = parsArgs(args); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java index a6592c9080..be8c60877c 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/comm/sock/SocketCommunicator.java @@ -223,6 +223,7 @@ public class SocketCommunicator implements ICommunicator { } }; + sendThread.setDaemon(true); sendThread.start(); try { @@ -478,7 +479,7 @@ public class SocketCommunicator implements ICommunicator { } - public synchronized DataTranfer sendToQEMU( + public synchronized DataTranfer sendDataToQEMU( SendCommand command, ISendData data, boolean useDataTransfer) { DataTranfer dataTranfer = null; diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomButton.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomButton.java index 2b0bc2a93f..716abfab19 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomButton.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/CustomButton.java @@ -244,4 +244,4 @@ public class CustomButton extends Canvas { return new Point(imageButton[0].getImageData().width, imageButton[0].getImageData().height); } -} +} \ No newline at end of file diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/KeyWindow.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/KeyWindow.java index dfd84770fd..54fae8ce6c 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/KeyWindow.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/custom/KeyWindow.java @@ -234,7 +234,7 @@ public class KeyWindow extends SkinWindow { /* attach HW keys */ if (keyMapList != null && keyMapList.isEmpty() == false) { for (KeyMapType keyEntry : keyMapList) { - CustomButton HWKeyButton = new CustomButton(composite, + final CustomButton HWKeyButton = new CustomButton(composite, SWT.NO_FOCUS, imageNormal, imageHover, imagePushed); HWKeyButton.setText(keyEntry.getEventInfo().getKeyName()); HWKeyButton.setToolTipText(keyEntry.getTooltip()); @@ -246,6 +246,8 @@ public class KeyWindow extends SkinWindow { HWKeyButton.addMouseListener(new MouseListener() { @Override public void mouseDown(MouseEvent e) { + logger.info(HWKeyButton.getText() + " key is pressed"); + KeyEventData keyEventData = new KeyEventData( KeyEventType.PRESSED.value(), keycode, 0, 0); communicator.sendToQEMU(SendCommand.SEND_HARD_KEY_EVENT, keyEventData); @@ -253,6 +255,8 @@ public class KeyWindow extends SkinWindow { @Override public void mouseUp(MouseEvent e) { + logger.info(HWKeyButton.getText() + " key is released"); + KeyEventData keyEventData = new KeyEventData( KeyEventType.RELEASED.value(), keycode, 0, 0); communicator.sendToQEMU(SendCommand.SEND_HARD_KEY_EVENT, keyEventData); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/AboutDialog.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/AboutDialog.java index bc79b17261..17acbf7d0a 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/AboutDialog.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/AboutDialog.java @@ -36,7 +36,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; @@ -45,7 +44,6 @@ import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.program.Program; -import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/DetailInfoDialog.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/DetailInfoDialog.java index d85c7370cd..ab615697b2 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/DetailInfoDialog.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/DetailInfoDialog.java @@ -207,7 +207,8 @@ public class DetailInfoDialog extends SkinDialog { String infoData = null; - DataTranfer dataTranfer = communicator.sendToQEMU( SendCommand.DETAIL_INFO, null, true ); + DataTranfer dataTranfer = + communicator.sendDataToQEMU(SendCommand.DETAIL_INFO, null, true); byte[] receivedData = communicator.getReceivedData( dataTranfer ); if ( null != receivedData ) { diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/SkinDialog.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/SkinDialog.java index 747bae5fde..6d47897da6 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/SkinDialog.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/dialog/SkinDialog.java @@ -1,7 +1,7 @@ /** * * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -121,7 +121,7 @@ public abstract class SkinDialog extends Dialog { if (y < monitorBounds.y) { y = monitorBounds.y; - } else if ((y + width) > (monitorBounds.y + monitorBounds.height)) { + } else if ((y + height) > (monitorBounds.y + monitorBounds.height)) { y = (monitorBounds.y + monitorBounds.height) - height; } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/GeneralPurposeSkinComposer.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/GeneralPurposeSkinComposer.java index dde649279b..280e608fcf 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/GeneralPurposeSkinComposer.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/GeneralPurposeSkinComposer.java @@ -1,5 +1,5 @@ /** - * + * General-Purpose Skin Layout * * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * @@ -48,8 +48,6 @@ import org.eclipse.swt.widgets.Shell; import org.tizen.emulator.skin.EmulatorSkin; import org.tizen.emulator.skin.EmulatorSkinState; import org.tizen.emulator.skin.comm.ICommunicator.RotationInfo; -import org.tizen.emulator.skin.comm.ICommunicator.SendCommand; -import org.tizen.emulator.skin.comm.sock.data.DisplayStateData; import org.tizen.emulator.skin.config.EmulatorConfig; import org.tizen.emulator.skin.config.EmulatorConfig.ArgsConstants; import org.tizen.emulator.skin.config.EmulatorConfig.SkinPropertiesConstants; @@ -90,9 +88,6 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { private MouseMoveListener shellMouseMoveListener; private MouseListener shellMouseListener; - private boolean isGrabbedShell; - private Point grabPosition; - public GeneralPurposeSkinComposer(EmulatorConfig config, EmulatorSkin skin, Shell shell, EmulatorSkinState currentState, ImageRegistry imageRegistry) { @@ -101,8 +96,6 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { this.shell = shell; this.currentState = currentState; this.imageRegistry = imageRegistry; - this.isGrabbedShell= false; - this.grabPosition = new Point(0, 0); this.frameMaker = new SkinPatches(PATCH_IMAGES_PATH); this.backgroundColor = new Color(shell.getDisplay(), new RGB(38, 38, 38)); @@ -143,6 +136,7 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { //shell.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_BLACK)); shell.setLocation(x, y); + /* This string must match the definition of Emulator-Manager */ String emulatorName = SkinUtil.makeEmulatorName(config); shell.setText("Emulator - " + emulatorName); @@ -230,9 +224,9 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { currentState.getCurrentResolutionHeight(), scale, rotationId); if (displayBounds == null) { - logger.severe("Failed to lcd information for phone shape skin."); + logger.severe("Failed to read display information for skin."); SkinUtil.openMessage(shell, null, - "Failed to read lcd information for phone shape skin.\n" + + "Failed to read display information for skin.\n" + "Check the contents of skin dbi file.", SWT.ICON_ERROR, config); System.exit(-1); @@ -268,13 +262,6 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { } /* set window size */ - if (currentState.getCurrentImage() != null) { - ImageData imageData = currentState.getCurrentImage().getImageData(); - shell.setMinimumSize(imageData.width, imageData.height); - } - - shell.pack(); - if (currentState.getCurrentImage() != null) { ImageData imageData = currentState.getCurrentImage().getImageData(); shell.setSize(imageData.width, imageData.height); @@ -375,19 +362,16 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { public void paintControl(final PaintEvent e) { if (currentState.isNeedToUpdateDisplay() == true) { currentState.setNeedToUpdateDisplay(false); + } - if (skin.communicator.isSensorDaemonStarted() == true) { - /* Let's do one more update for sdl display surface - while skipping of framebuffer drawing */ - DisplayStateData lcdStateData = new DisplayStateData( - currentState.getCurrentScale(), currentState.getCurrentRotationId()); - skin.communicator.sendToQEMU( - SendCommand.CHANGE_LCD_STATE, lcdStateData, false); - } + /* set window size once again (for ubuntu 12.04) */ + if (currentState.getCurrentImage() != null) { + ImageData imageData = currentState.getCurrentImage().getImageData(); + shell.setSize(imageData.width, imageData.height); } /* general shell does not support native transparency, - * so draw image with GC. */ + so draw image with GC */ if (currentState.getCurrentImage() != null) { e.gc.drawImage(currentState.getCurrentImage(), 0, 0); } @@ -405,13 +389,16 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { shellMouseMoveListener = new MouseMoveListener() { @Override public void mouseMove(MouseEvent e) { - if (isGrabbedShell == true && e.button == 0/* left button */) { + if (skin.isShellGrabbing() == true && e.button == 0/* left button */) { /* move a window */ Point previousLocation = shell.getLocation(); - int x = previousLocation.x + (e.x - grabPosition.x); - int y = previousLocation.y + (e.y - grabPosition.y); + Point grabLocation = skin.getGrabPosition(); + if (grabLocation != null) { + int x = previousLocation.x + (e.x - grabLocation.x); + int y = previousLocation.y + (e.y - grabLocation.y); - shell.setLocation(x, y); + shell.setLocation(x, y); + } if (skin.keyWindow != null && skin.keyWindow.getDockPosition() != SWT.NONE) { @@ -430,8 +417,7 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { if (e.button == 1) { /* left button */ logger.info("mouseUp in Skin"); - isGrabbedShell = false; - grabPosition.x = grabPosition.y = 0; + skin.ungrabShell(); if (skin.keyWindow != null && skin.keyWindow.getDockPosition() != SWT.NONE) { @@ -446,9 +432,7 @@ public class GeneralPurposeSkinComposer implements ISkinComposer { if (1 == e.button) { /* left button */ logger.info("mouseDown in Skin"); - isGrabbedShell = true; - grabPosition.x = e.x; - grabPosition.y = e.y; + skin.grabShell(e.x, e.y); } } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/HWKey.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/HWKey.java index 32b18c08e2..257f476f0e 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/HWKey.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/HWKey.java @@ -1,7 +1,7 @@ /** + * Hardware Key * - * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -32,14 +32,35 @@ import org.tizen.emulator.skin.util.SkinRegion; import org.tizen.emulator.skin.util.SkinUtil; public class HWKey { + private String name; private int keyCode; private SkinRegion region; private String tooltip; + /** + * Constructor + */ public HWKey() { + this.name = "unknown"; this.keyCode = SkinUtil.UNKNOWN_KEYCODE; } + public HWKey(String name, int keyCode, SkinRegion region, String tooltip) { + this.name = name; + this.keyCode = keyCode; + this.region = region; + this.tooltip = tooltip; + } + + /* name */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + /* keycode */ public int getKeyCode() { return keyCode; diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/PhoneShapeSkinComposer.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/ProfileSpecificSkinComposer.java similarity index 84% rename from tizen/src/skin/client/src/org/tizen/emulator/skin/layout/PhoneShapeSkinComposer.java rename to tizen/src/skin/client/src/org/tizen/emulator/skin/layout/ProfileSpecificSkinComposer.java index efa674aa7b..515da2dd51 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/PhoneShapeSkinComposer.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/ProfileSpecificSkinComposer.java @@ -1,7 +1,7 @@ /** - * + * Profile-Specific Skin Layout * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -52,7 +52,6 @@ import org.tizen.emulator.skin.EmulatorSkinState; import org.tizen.emulator.skin.comm.ICommunicator.KeyEventType; import org.tizen.emulator.skin.comm.ICommunicator.SendCommand; import org.tizen.emulator.skin.comm.sock.SocketCommunicator; -import org.tizen.emulator.skin.comm.sock.data.DisplayStateData; import org.tizen.emulator.skin.comm.sock.data.KeyEventData; import org.tizen.emulator.skin.config.EmulatorConfig; import org.tizen.emulator.skin.config.EmulatorConfig.ArgsConstants; @@ -69,9 +68,9 @@ import org.tizen.emulator.skin.util.SkinRotation; import org.tizen.emulator.skin.util.SkinUtil; import org.tizen.emulator.skin.util.SwtUtil; -public class PhoneShapeSkinComposer implements ISkinComposer { +public class ProfileSpecificSkinComposer implements ISkinComposer { private Logger logger = SkinLogger.getSkinLogger( - PhoneShapeSkinComposer.class).getLogger(); + ProfileSpecificSkinComposer.class).getLogger(); private EmulatorConfig config; private EmulatorSkin skin; @@ -86,10 +85,7 @@ public class PhoneShapeSkinComposer implements ISkinComposer { private MouseMoveListener shellMouseMoveListener; private MouseListener shellMouseListener; - private boolean isGrabbedShell; - private Point grabPosition; - - public PhoneShapeSkinComposer(EmulatorConfig config, EmulatorSkin skin, + public ProfileSpecificSkinComposer(EmulatorConfig config, EmulatorSkin skin, Shell shell, EmulatorSkinState currentState, ImageRegistry imageRegistry, SocketCommunicator communicator) { this.config = config; @@ -98,8 +94,6 @@ public class PhoneShapeSkinComposer implements ISkinComposer { this.currentState = currentState; this.imageRegistry = imageRegistry; this.communicator = communicator; - this.isGrabbedShell= false; - this.grabPosition = new Point(0, 0); } @Override @@ -136,6 +130,7 @@ public class PhoneShapeSkinComposer implements ISkinComposer { //shell.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_BLACK)); shell.setLocation(x, y); + /* This string must match the definition of Emulator-Manager */ String emulatorName = SkinUtil.makeEmulatorName(config); shell.setText("Emulator - " + emulatorName); @@ -174,19 +169,16 @@ public class PhoneShapeSkinComposer implements ISkinComposer { currentState.getCurrentResolutionHeight(), scale, rotationId); if (lcdBounds == null) { - logger.severe("Failed to lcd information for phone shape skin."); + logger.severe("Failed to read display information for skin."); SkinUtil.openMessage(shell, null, - "Failed to read lcd information for phone shape skin.\n" + + "Failed to read display information for skin.\n" + "Check the contents of skin dbi file.", SWT.ICON_ERROR, config); System.exit(-1); } - logger.info("lcd bounds : " + lcdBounds); + logger.info("display bounds : " + lcdBounds); currentState.setDisplayBounds(lcdBounds); - if (SwtUtil.isMacPlatform() == true) { - lcdCanvas.setBounds(currentState.getDisplayBounds()); - } /* arrange the skin image */ Image tempImage = null; @@ -211,20 +203,16 @@ public class PhoneShapeSkinComposer implements ISkinComposer { tempKeyPressedImage.dispose(); } + if (SwtUtil.isMacPlatform() == true) { + lcdCanvas.setBounds(currentState.getDisplayBounds()); + } + /* arrange the progress bar */ if (skin.bootingProgress != null) { skin.bootingProgress.setBounds(lcdBounds.x, lcdBounds.y + lcdBounds.height + 1, lcdBounds.width, 2); } - /* set window size */ - if (currentState.getCurrentImage() != null) { - ImageData imageData = currentState.getCurrentImage().getImageData(); - shell.setMinimumSize(imageData.width, imageData.height); - } - - shell.pack(); - /* set window size */ if (currentState.getCurrentImage() != null) { ImageData imageData = currentState.getCurrentImage().getImageData(); @@ -276,22 +264,20 @@ public class PhoneShapeSkinComposer implements ISkinComposer { public void paintControl(final PaintEvent e) { if (currentState.isNeedToUpdateDisplay() == true) { currentState.setNeedToUpdateDisplay(false); + if (SwtUtil.isMacPlatform() == false) { lcdCanvas.setBounds(currentState.getDisplayBounds()); } + } - if (skin.communicator.isSensorDaemonStarted() == true) { - /* Let's do one more update for sdl display surface - while skipping of framebuffer drawing */ - DisplayStateData lcdStateData = new DisplayStateData( - currentState.getCurrentScale(), currentState.getCurrentRotationId()); - skin.communicator.sendToQEMU( - SendCommand.CHANGE_LCD_STATE, lcdStateData, false); - } + /* set window size once again (for ubuntu 12.04) */ + if (currentState.getCurrentImage() != null) { + ImageData imageData = currentState.getCurrentImage().getImageData(); + shell.setSize(imageData.width, imageData.height); } /* general shell does not support native transparency, - * so draw image with GC. */ + so draw image with GC */ if (currentState.getCurrentImage() != null) { e.gc.drawImage(currentState.getCurrentImage(), 0, 0); } @@ -325,24 +311,27 @@ public class PhoneShapeSkinComposer implements ISkinComposer { shellMouseMoveListener = new MouseMoveListener() { @Override public void mouseMove(MouseEvent e) { - if (isGrabbedShell == true && e.button == 0/* left button */ && - currentState.getCurrentPressedHWKey() == null) { + if (skin.isShellGrabbing() == true && e.button == 0/* left button */ + && currentState.getCurrentPressedHWKey() == null) { /* move a window */ Point previousLocation = shell.getLocation(); - int x = previousLocation.x + (e.x - grabPosition.x); - int y = previousLocation.y + (e.y - grabPosition.y); + Point grabLocation = skin.getGrabPosition(); + if (grabLocation != null) { + int x = previousLocation.x + (e.x - grabLocation.x); + int y = previousLocation.y + (e.y - grabLocation.y); - shell.setLocation(x, y); + shell.setLocation(x, y); + } return; } final HWKey hwKey = SkinUtil.getHWKey(e.x, e.y, currentState.getCurrentRotationId(), currentState.getCurrentScale()); - if (hwKey == null) { - /* remove hover */ - HWKey hoveredHWKey = currentState.getCurrentHoveredHWKey(); + final HWKey hoveredHWKey = currentState.getCurrentHoveredHWKey(); + if (hwKey == null) { if (hoveredHWKey != null) { + /* remove hover */ shell.redraw(hoveredHWKey.getRegion().x, hoveredHWKey.getRegion().y, hoveredHWKey.getRegion().width, @@ -356,30 +345,41 @@ public class PhoneShapeSkinComposer implements ISkinComposer { } /* register a tooltip */ - if (currentState.getCurrentHoveredHWKey() == null && + if (hoveredHWKey == null && hwKey.getTooltip().isEmpty() == false) { shell.setToolTipText(hwKey.getTooltip()); - } - - /* draw hover */ - shell.getDisplay().syncExec(new Runnable() { - public void run() { - if (hwKey.getRegion().width != 0 && hwKey.getRegion().height != 0) { - GC gc = new GC(shell); - if (gc != null) { - gc.setLineWidth(1); - gc.setForeground(currentState.getHoverColor()); - gc.drawRectangle(hwKey.getRegion().x, hwKey.getRegion().y, - hwKey.getRegion().width - 1, hwKey.getRegion().height - 1); - - gc.dispose(); - currentState.setCurrentHoveredHWKey(hwKey); + currentState.setCurrentHoveredHWKey(hwKey); + + /* draw hover */ + shell.getDisplay().syncExec(new Runnable() { + public void run() { + if (hwKey.getRegion().width != 0 && hwKey.getRegion().height != 0) { + GC gc = new GC(shell); + if (gc != null) { + gc.setLineWidth(1); + gc.setForeground(currentState.getHoverColor()); + gc.drawRectangle(hwKey.getRegion().x, hwKey.getRegion().y, + hwKey.getRegion().width - 1, hwKey.getRegion().height - 1); + + gc.dispose(); + } } } - } - }); + }); + } else { + if (hwKey.getRegion().x != hoveredHWKey.getRegion().x || + hwKey.getRegion().y != hoveredHWKey.getRegion().y) { + /* remove hover */ + shell.redraw(hoveredHWKey.getRegion().x, + hoveredHWKey.getRegion().y, + hoveredHWKey.getRegion().width, + hoveredHWKey.getRegion().height, false); + currentState.setCurrentHoveredHWKey(null); + shell.setToolTipText(null); + } + } } }; @@ -389,17 +389,17 @@ public class PhoneShapeSkinComposer implements ISkinComposer { @Override public void mouseUp(MouseEvent e) { if (e.button == 1) { /* left button */ - logger.info("mouseUp in Skin"); - - isGrabbedShell = false; - grabPosition.x = grabPosition.y = 0; + skin.ungrabShell(); HWKey pressedHWKey = currentState.getCurrentPressedHWKey(); if (pressedHWKey == null) { + logger.info("mouseUp in Skin"); return; } if (pressedHWKey.getKeyCode() != SkinUtil.UNKNOWN_KEYCODE) { + logger.info(pressedHWKey.getName() + " key is released"); + /* send event */ KeyEventData keyEventData = new KeyEventData( KeyEventType.RELEASED.value(), pressedHWKey.getKeyCode(), 0, 0); @@ -423,19 +423,19 @@ public class PhoneShapeSkinComposer implements ISkinComposer { @Override public void mouseDown(MouseEvent e) { if (1 == e.button) { /* left button */ - logger.info("mouseDown in Skin"); - - isGrabbedShell = true; - grabPosition.x = e.x; - grabPosition.y = e.y; + skin.grabShell(e.x, e.y); + /* HW key handling */ final HWKey hwKey = SkinUtil.getHWKey(e.x, e.y, currentState.getCurrentRotationId(), currentState.getCurrentScale()); if (hwKey == null) { + logger.info("mouseDown in Skin"); return; } if (hwKey.getKeyCode() != SkinUtil.UNKNOWN_KEYCODE) { + logger.info(hwKey.getName() + " key is pressed"); + /* send event */ KeyEventData keyEventData = new KeyEventData( KeyEventType.PRESSED.value(), hwKey.getKeyCode(), 0, 0); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/SkinPatches.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/SkinPatches.java index 5ca395f7da..1161364139 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/SkinPatches.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/layout/SkinPatches.java @@ -1,7 +1,7 @@ /** + * General Skin Frame Maker * - * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -100,6 +100,8 @@ public class SkinPatches { // TODO: copy alphaData GC gc = new GC(patchedImage); + //gc.setInterpolation(SWT.NONE); + gc.setBackground(display.getSystemColor(SWT.COLOR_MAGENTA)); gc.fillRectangle(0, 0, patchedImageWidth, patchedImageHeight); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/ScreenShotDialog.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/ScreenShotDialog.java index 5c62469d67..c7449209a9 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/ScreenShotDialog.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/ScreenShotDialog.java @@ -1,7 +1,7 @@ /** * Capture a screenshot of the Emulator framebuffer * - * Copyright ( C ) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * GiWoong Kim @@ -11,7 +11,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or ( at your option ) any later version. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -126,13 +126,20 @@ public class ScreenShotDialog { this.config = config; this.scaleLevel = 100d; - shell = new Shell(Display.getDefault(), SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX); + if (!SwtUtil.isMacPlatform()) { + shell = new Shell(parent, SWT.SHELL_TRIM); + } else { + shell = new Shell(parent.getDisplay(), SWT.SHELL_TRIM); + } shell.setText("Screen Shot - " + SkinUtil.makeEmulatorName(config)); - if(!SwtUtil.isMacPlatform()) { - if (icon != null) { - shell.setImage(icon); - } - } + + /* To prevent the icon switching on Mac */ + if (!SwtUtil.isMacPlatform()) { + if (icon != null) { + shell.setImage(icon); + } + } + shell.addListener( SWT.Close, new Listener() { @Override public void handleEvent( Event event ) { @@ -225,27 +232,33 @@ public class ScreenShotDialog { // } // }); - Rectangle monitorBound = Display.getDefault().getBounds(); - logger.info("host monitor display bound : " + monitorBound); - Rectangle emulatorBound = parent.getBounds(); - logger.info("current Emulator window bound : " + emulatorBound); - Rectangle dialogBound = shell.getBounds(); - logger.info("current ScreenShot Dialog bound : " + dialogBound); + Rectangle monitorBounds = Display.getDefault().getBounds(); + logger.info("host monitor display bounds : " + monitorBounds); + Rectangle emulatorBounds = parent.getBounds(); + logger.info("current Emulator window bounds : " + emulatorBounds); + Rectangle dialogBounds = shell.getBounds(); + logger.info("current ScreenShot Dialog bounds : " + dialogBounds); /* size correction */ - shell.setSize(emulatorBound.width, emulatorBound.height); - dialogBound = shell.getBounds(); - logger.info("current ScreenShot Dialog bound : " + dialogBound); + shell.setSize(emulatorBounds.width, emulatorBounds.height); + dialogBounds = shell.getBounds(); + logger.info("current ScreenShot Dialog bound : " + dialogBounds); /* location correction */ - int x = emulatorBound.x + emulatorBound.width + 20; - int y = emulatorBound.y; - if ((x + dialogBound.width) > (monitorBound.x + monitorBound.width)) { - x = emulatorBound.x - dialogBound.width - 20; + int x = emulatorBounds.x + emulatorBounds.width + 20; + int y = emulatorBounds.y; + if ((x + dialogBounds.width) > (monitorBounds.x + monitorBounds.width)) { + x = emulatorBounds.x - dialogBounds.width - 20; + } + if (y < monitorBounds.y) { + y = monitorBounds.y; + } else if ((y + dialogBounds.height) > (monitorBounds.y + monitorBounds.height)) { + y = (monitorBounds.y + monitorBounds.height) - dialogBounds.height; } shell.setLocation(x, y); - dialogBound = shell.getBounds(); - logger.info("current ScreenShot Dialog bound : " + dialogBound); + + dialogBounds = shell.getBounds(); + logger.info("current ScreenShot Dialog bound : " + dialogBounds); } diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/SdlScreenShotWindow.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/SdlScreenShotWindow.java index d482afce7d..7cbc728530 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/SdlScreenShotWindow.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/SdlScreenShotWindow.java @@ -59,7 +59,7 @@ public class SdlScreenShotWindow extends ScreenShotDialog { } protected void capture() throws ScreenShotException { - DataTranfer dataTranfer = communicator.sendToQEMU( + DataTranfer dataTranfer = communicator.sendDataToQEMU( SendCommand.SCREEN_SHOT, null, true); byte[] receivedData = communicator.getReceivedData(dataTranfer); diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/util/CocoaUtil.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/util/CocoaUtil.java new file mode 100755 index 0000000000..430df17a0d --- /dev/null +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/util/CocoaUtil.java @@ -0,0 +1,106 @@ +/** + * + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Munkyu Im + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +package org.tizen.emulator.skin.util; + +import java.lang.reflect.InvocationTargetException; + +public class CocoaUtil { + + private static final long aboutMenuValue = 0; + private static final long prefMenuValue = 2; + public static final String NSApplication_CLASS = "org.eclipse.swt.internal.cocoa.NSApplication"; + public static final String NSMenu_CLASS = "org.eclipse.swt.internal.cocoa.NSMenu"; + public static final String NSMenuItem_CLASS = "org.eclipse.swt.internal.cocoa.NSMenuItem"; + + public static Object invokeMethod(Class clazz, Object object, String method, Object[] args) + throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, + SecurityException, NoSuchMethodException { + Class[] signature = new Class[args.length]; + for (int i = 0; i < args.length; i++) { + Class thisClass = args[i].getClass(); + if (thisClass == Integer.class) + signature[i] = int.class; + else if (thisClass == Long.class) + signature[i] = long.class; + else if (thisClass == Byte.class) + signature[i] = byte.class; + else if ( thisClass == Boolean.class ) + signature[i] = boolean.class; + else + signature[i] = thisClass; + } + return clazz.getDeclaredMethod(method, signature).invoke(object, args); + } + + // remove about and preference menu item + public void removeTopMenuItems() { + try { + Class nsmenuClass = Class.forName(NSMenu_CLASS); + Class nsmenuitemClass = Class.forName(NSMenuItem_CLASS); + Class nsapplicationClass = Class.forName(NSApplication_CLASS); + + Object sharedApplication = nsapplicationClass.getDeclaredMethod( + "sharedApplication", (Class[]) null).invoke(null, + (Object[]) null); + Object mainMenu = sharedApplication.getClass() + .getDeclaredMethod("mainMenu", (Class[]) null) + .invoke(sharedApplication, (Object[]) null); + + Object mainMenuItem = invokeMethod(nsmenuClass, mainMenu, + "itemAtIndex", new Object[] { new Long(0) }); + Object appMenu = mainMenuItem.getClass() + .getDeclaredMethod("submenu", (Class[]) null) + .invoke(mainMenuItem, (Object[]) null); + + Object aboutMenuItem = invokeMethod(nsmenuClass, appMenu, + "itemAtIndex", new Object[] { new Long(aboutMenuValue) }); + Object prefMenuItem = invokeMethod(nsmenuClass, appMenu, + "itemAtIndex", new Object[] { new Long(prefMenuValue) }); + + //set hidden + invokeMethod(nsmenuitemClass, aboutMenuItem, "setHidden", + new Object[] { new Boolean(true) }); + invokeMethod(nsmenuitemClass, prefMenuItem, "setHidden", + new Object[] { new Boolean(true) }); + + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } +} diff --git a/tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java b/tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java index b4d0a51024..bc344781b8 100644 --- a/tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java +++ b/tizen/src/skin/client/src/org/tizen/emulator/skin/util/SkinUtil.java @@ -107,7 +107,7 @@ public class SkinUtil { vmName = EMULATOR_PREFIX; } - int portNumber = config.getArgInt( ArgsConstants.NET_BASE_PORT ); + int portNumber = config.getArgInt( ArgsConstants.NET_BASE_PORT ) + 1; return vmName + ":" + portNumber; } @@ -160,21 +160,23 @@ public class SkinUtil { return null; } - for (KeyMapType keyMap : keyMapList) { - RegionType region = keyMap.getRegion(); + for (KeyMapType keyEntry : keyMapList) { + RegionType region = keyEntry.getRegion(); int scaledX = (int) (region.getLeft() * convertedScale); int scaledY = (int) (region.getTop() * convertedScale); int scaledWidth = (int) (region.getWidth() * convertedScale); int scaledHeight = (int) (region.getHeight() * convertedScale); - if (isInGeometry(currentX, currentY, scaledX, scaledY, scaledWidth, scaledHeight)) { - EventInfoType eventInfo = keyMap.getEventInfo(); + if (isInGeometry(currentX, currentY, + scaledX, scaledY, scaledWidth, scaledHeight)) { + EventInfoType eventInfo = keyEntry.getEventInfo(); - HWKey hwKey = new HWKey(); - hwKey.setKeyCode(eventInfo.getKeyCode()); - hwKey.setRegion(new SkinRegion(scaledX, scaledY, scaledWidth, scaledHeight)); - hwKey.setTooltip(keyMap.getTooltip()); + HWKey hwKey = new HWKey( + keyEntry.getEventInfo().getKeyName(), + eventInfo.getKeyCode(), + new SkinRegion(scaledX, scaledY, scaledWidth, scaledHeight), + keyEntry.getTooltip()); return hwKey; } diff --git a/tizen/src/skin/maruskin_operation.c b/tizen/src/skin/maruskin_operation.c index 65c6b3dd29..c724f30f9f 100644 --- a/tizen/src/skin/maruskin_operation.c +++ b/tizen/src/skin/maruskin_operation.c @@ -40,7 +40,6 @@ #include "emulator.h" #include "debug_ch.h" #include "sdb.h" -#include "qemu_socket.h" #include "mloop_event.h" #include "emul_state.h" #include "maruskin_keymap.h" @@ -50,6 +49,12 @@ #include "sysemu.h" #include "sysbus.h" +#if defined(_WIN32) +#include "nbd.h" +#else +#include "qemu_socket.h" +#endif + #ifdef CONFIG_HAX #include "guest_debug.h" @@ -85,20 +90,30 @@ void start_display(uint64 handle_id, int lcd_size_width, int lcd_size_height, double scale_factor, short rotation_type) { - INFO("start_display handle_id:%ld, lcd size:%dx%d, scale_factor:%f, rotation_type:%d\n", - (long)handle_id, lcd_size_width, lcd_size_height, scale_factor, rotation_type); + INFO("start_display handle_id:%ld, display size:%dx%d, \ +scale_factor:%f, rotation_type:%d\n", + (long) handle_id, lcd_size_width, lcd_size_height, + scale_factor, rotation_type); set_emul_win_scale(scale_factor); - maruskin_init(handle_id, lcd_size_width, lcd_size_height, false); + maruskin_init(handle_id, lcd_size_width, lcd_size_height); } void do_mouse_event(int button_type, int event_type, int origin_x, int origin_y, int x, int y, int z) { if (brightness_off) { - TRACE("reject mouse touch in lcd off = button:%d, type:%d, x:%d, y:%d, z:%d\n", - button_type, event_type, x, y, z); - return; + if (button_type == 0) { + INFO("auto mouse release\n"); + kbd_mouse_event(0, 0, 0, 0); + + return; + } else { + TRACE("reject mouse touch in display off : " + "button=%d, type=%d, x=%d, y=%d, z=%d\n", + button_type, event_type, x, y, z); + return; + } } TRACE("mouse_event button:%d, type:%d, host:(%d, %d), x:%d, y:%d, z:%d\n", @@ -126,7 +141,7 @@ void do_mouse_event(int button_type, int event_type, kbd_mouse_event(x, y, z, 1); TRACE("mouse_event event_type:%d, origin:(%d, %d), x:%d, y:%d, z:%d\n\n", - event_type, origin_x, origin_y, x, y, z); + event_type, origin_x, origin_y, x, y, z); break; case MOUSE_UP: guest_x = x; @@ -136,7 +151,7 @@ void do_mouse_event(int button_type, int event_type, kbd_mouse_event(x, y, z, 0); TRACE("mouse_event event_type:%d, origin:(%d, %d), x:%d, y:%d, z:%d\n\n", - event_type, origin_x, origin_y, x, y, z); + event_type, origin_x, origin_y, x, y, z); break; case MOUSE_WHEELUP: case MOUSE_WHEELDOWN: @@ -147,7 +162,7 @@ void do_mouse_event(int button_type, int event_type, kbd_mouse_event(x, y, -z, event_type); TRACE("mouse_event event_type:%d, origin:(%d, %d), x:%d, y:%d, z:%d\n\n", - event_type, origin_x, origin_y, x, y, z); + event_type, origin_x, origin_y, x, y, z); break; default: ERR("undefined mouse event type passed:%d\n", event_type); @@ -304,6 +319,14 @@ void do_rotation_event(int rotation_type) INFO( "do_rotation_event rotation_type:%d\n", rotation_type); + set_emul_rotation( rotation_type ); +} + +void send_rotation_event(int rotation_type) +{ + + INFO( "send_rotation_event rotation_type:%d\n", rotation_type); + char send_buf[32] = { 0 }; switch ( rotation_type ) { @@ -325,38 +348,49 @@ void do_rotation_event(int rotation_type) } send_to_emuld( "sensor\n\n\n\n", 10, send_buf, 32 ); - - set_emul_rotation( rotation_type ); - } -QemuSurfaceInfo* get_screenshot_info(void) +void set_maru_screenshot(DisplayState *ds) { - DisplaySurface* qemu_display_surface = get_qemu_display_surface(); + pthread_mutex_lock(&mutex_screenshot); - if ( !qemu_display_surface ) { - ERR( "qemu surface is NULL.\n" ); - return NULL; + MaruScreenshot *maru_screenshot = get_maru_screenshot(); + if (maru_screenshot) { + maru_screenshot->isReady = 1; + if (maru_screenshot->request_screenshot == 1) { + memcpy(maru_screenshot->pixel_data, + ds_get_data(ds), + ds_get_linesize(ds) * + ds_get_height(ds)); + maru_screenshot->request_screenshot = 0; + + pthread_cond_signal(&cond_screenshot); + } } + pthread_mutex_unlock(&mutex_screenshot); +} - QemuSurfaceInfo* info = (QemuSurfaceInfo*) g_malloc0( sizeof(QemuSurfaceInfo) ); - if ( !info ) { - ERR( "Fail to malloc for QemuSurfaceInfo.\n"); +QemuSurfaceInfo *get_screenshot_info(void) +{ + QemuSurfaceInfo *info = + (QemuSurfaceInfo *)g_malloc0(sizeof(QemuSurfaceInfo)); + if (!info) { + ERR("Fail to malloc for QemuSurfaceInfo.\n"); return NULL; } - int length = qemu_display_surface->linesize * qemu_display_surface->height; - INFO( "screenshot data length:%d\n", length ); + int length = get_emul_lcd_width() * get_emul_lcd_height() * 4; + INFO("screenshot data length:%d\n", length); - if ( 0 >= length ) { - g_free( info ); - ERR( "screenshot data ( 0 >=length ). length:%d\n", length ); + if (0 >= length) { + g_free(info); + ERR("screenshot data ( 0 >=length ). length:%d\n", length); return NULL; } - info->pixel_data = (unsigned char*) g_malloc0( length ); - if ( !info->pixel_data ) { - g_free( info ); + info->pixel_data = (unsigned char *)g_malloc0(length); + if (!info->pixel_data) { + g_free(info); ERR("Fail to malloc for pixel data.\n"); return NULL; } @@ -385,7 +419,7 @@ QemuSurfaceInfo* get_screenshot_info(void) return info; } -void free_screenshot_info(QemuSurfaceInfo* info) +void free_screenshot_info(QemuSurfaceInfo *info) { if (info) { if(info->pixel_data) { @@ -582,11 +616,15 @@ static void* run_timed_shutdown_thread(void* args) static void send_to_emuld(const char* request_type, int request_size, const char* send_buf, int buf_size) { +#if defined(_WIN32) + int s = tcp_socket_outgoing( "127.0.0.1", (uint16_t) ( tizen_base_port + SDB_TCP_EMULD_INDEX ) ); +#else char addr[128]; int s = 0; snprintf(addr, 128, ":%u", (uint16_t) (tizen_base_port + SDB_TCP_EMULD_INDEX)); s = inet_connect(addr, true, NULL, NULL); +#endif if ( s < 0 ) { ERR( "can't create socket to emulator daemon in guest\n" ); diff --git a/tizen/src/skin/maruskin_operation.h b/tizen/src/skin/maruskin_operation.h index 1c03d86674..0ef20c90e9 100644 --- a/tizen/src/skin/maruskin_operation.h +++ b/tizen/src/skin/maruskin_operation.h @@ -57,6 +57,7 @@ void do_key_event(int event_type, void do_hardkey_event(int event_type, int keycode); void do_scale_event(double scale_factor); void do_rotation_event(int rotation_type); +void send_rotation_event(int rotation_type); QemuSurfaceInfo *get_screenshot_info(void); DetailInfo *get_detail_info(int qemu_argc, char **qemu_argv); diff --git a/tizen/src/skin/maruskin_server.c b/tizen/src/skin/maruskin_server.c index 63c2f57888..4b96bec729 100644 --- a/tizen/src/skin/maruskin_server.c +++ b/tizen/src/skin/maruskin_server.c @@ -277,7 +277,7 @@ void shutdown_skin_server(void) void notify_sdb_daemon_start(void) { - INFO("notify_sensor_daemon_start\n"); + INFO("notify_sdb_daemon_start\n"); is_sdbd_initialized = 1; if (client_sock) { @@ -870,6 +870,7 @@ static void* run_skin_server(void* args) int scale = 0; double scale_ratio = 0.0; short rotation_type = 0; + int is_rotate = 0; char* p = recvbuf; memcpy( &scale, p, sizeof( scale ) ); @@ -886,11 +887,16 @@ static void* run_skin_server(void* args) if ( is_sensord_initialized == 1 && get_emul_rotation() != rotation_type ) { do_rotation_event( rotation_type ); + is_rotate = 1; } #ifndef CONFIG_USE_SHM maruskin_sdl_resize(); // send sdl event #endif + if (is_rotate) { + send_rotation_event( rotation_type ); + } + break; } case RECV_SCREEN_SHOT: { -- 2.34.1