Simple DirectMedia Layer
|
심플 다이렉트미디어 레이어(Simple DirectMedia Layer), SDL는 C 프로그래밍 언어로 짜여진 크로스플랫폼 멀티미디어 라이브러리이다. 이 라이브러리는 비디오, 오디오, 사용자 입력 등의 계층을 추상화하여, 리눅스, 마이크로소프트 윈도, 맥 OS X 등 여러 운영 체제에서 실행이 가능하도록 한다. 이 라이브러리는 비디오, 이벤트, 디지털 오디오, CD-ROM, 사운드, 스레드, 공유 객체 불러오기, 네트워킹, 타이머를 관리한다.
SDL 2.0 API by Category
|
|
|
|
|
|
|
|
|
|
|
|
Structure
Libraries
SDL3
- SDL3/FrontPage - SDL Wiki
- libsdl-org/SDL: Simple Directmedia Layer
- Simple DirectMedia Layer - Language Bindings
- Lazy Foo' Productions - Beginning Game Programming v3.0
Local Download
- SDL2 2.0.4
-
SDL2-2.0.4.tar.gz
SDL 환경변수 자동 감지 및 설정
pygame + opengl + linux 에서 실행하면 SDL 관련 환경변수를 설정해야 정상적으로 실행되는 이슈가 있음.
이런 환경변수 알아서 잘 찾아서 설정하여 실행되게 하는 방법이 필요함.
| WARNING |
| Claude-Code에서 자동 생성한 답변이다 |
주요 문제 패턴들
# 흔히 발생하는 케이스들
SDL_VIDEODRIVER=wayland → X11 앱이 깨지는 경우
SDL_VIDEODRIVER=x11 → Wayland 전용 환경에서 필요
DISPLAY=:0 → X11 디스플레이 미설정
LIBGL_ALWAYS_SOFTWARE=1 → GPU 드라이버 문제
SDL_VIDEO_X11_FORCE_EGL=1 → EGL 강제 필요한 경우
자동 감지 Python 모듈
import os
import subprocess
import sys
from pathlib import Path
def detect_display_server() -> str:
"""
Detect current display server (Wayland or X11)
현재 디스플레이 서버 감지
"""
# Wayland 세션 확인
if os.environ.get("WAYLAND_DISPLAY"):
return "wayland"
if os.environ.get("XDG_SESSION_TYPE", "").lower() == "wayland":
return "wayland"
# X11 세션 확인
if os.environ.get("DISPLAY"):
return "x11"
return "unknown"
def find_x11_display() -> str | None:
"""
Find available X11 DISPLAY value
사용 가능한 X11 DISPLAY 값 찾기
"""
# 이미 설정된 경우
if os.environ.get("DISPLAY"):
return os.environ["DISPLAY"]
# /tmp/.X11-unix 소켓 탐색
x11_dir = Path("/tmp/.X11-unix")
if x11_dir.exists():
sockets = sorted(x11_dir.glob("X*"))
if sockets:
# X0 -> :0, X1 -> :1 ...
display_num = sockets[0].name[1:] # 'X' 제거
return f":{display_num}"
return None
def check_opengl_support() -> dict:
"""
Check OpenGL driver availability via glxinfo
glxinfo로 OpenGL 드라이버 가용성 확인
"""
result = {"has_glx": False, "has_egl": False, "renderer": "unknown"}
try:
out = subprocess.check_output(
["glxinfo", "-B"],
stderr=subprocess.DEVNULL,
timeout=3,
).decode()
result["has_glx"] = True
for line in out.splitlines():
if "OpenGL renderer" in line:
result["renderer"] = line.split(":", 1)[-1].strip()
except (FileNotFoundError, subprocess.CalledProcessError, subprocess.TimeoutExpired):
pass
# EGL 확인
try:
out = subprocess.check_output(
["eglinfo"],
stderr=subprocess.DEVNULL,
timeout=3,
).decode()
result["has_egl"] = "EGL_VERSION" in out
except (FileNotFoundError, subprocess.CalledProcessError, subprocess.TimeoutExpired):
pass
return result
def is_ssh_session() -> bool:
"""
Detect if running inside SSH session
SSH 세션 여부 감지
"""
return bool(os.environ.get("SSH_CLIENT") or os.environ.get("SSH_TTY"))
def is_virtual_machine() -> bool:
"""
Detect if running inside a virtual machine (VirtualBox, VMware, etc.)
가상머신 여부 감지
"""
try:
out = subprocess.check_output(
["systemd-detect-virt", "--vm"],
stderr=subprocess.DEVNULL,
timeout=2,
).decode().strip()
return out not in ("none", "")
except Exception:
pass
# /sys/class/dmi로 폴백
try:
dmi = Path("/sys/class/dmi/id/product_name").read_text().lower()
return any(v in dmi for v in ("virtualbox", "vmware", "kvm", "qemu"))
except Exception:
return False
def resolve_sdl_env() -> dict[str, str]:
"""
Automatically resolve required SDL environment variables
필요한 SDL 환경변수 자동 결정
Returns:
dict: 설정해야 할 환경변수 딕셔너리
"""
env_patch: dict[str, str] = {}
display_server = detect_display_server()
opengl_info = check_opengl_support()
ssh = is_ssh_session()
vm = is_virtual_machine()
print(f"[sdl_env] Display server : {display_server}")
print(f"[sdl_env] SSH session : {ssh}")
print(f"[sdl_env] Virtual machine: {vm}")
print(f"[sdl_env] OpenGL renderer: {opengl_info['renderer']}")
# ── DISPLAY 설정 (X11) ──────────────────────────────────────
if not os.environ.get("DISPLAY"):
found = find_x11_display()
if found:
env_patch["DISPLAY"] = found
print(f"[sdl_env] DISPLAY 자동 설정: {found}")
# ── SDL_VIDEODRIVER ──────────────────────────────────────────
if not os.environ.get("SDL_VIDEODRIVER"):
if ssh or vm:
# SSH/VM 환경: offscreen 또는 x11 강제
env_patch["SDL_VIDEODRIVER"] = "x11"
elif display_server == "wayland":
# Wayland + OpenGL 조합은 x11로 강제하는 게 안정적
env_patch["SDL_VIDEODRIVER"] = "x11"
elif display_server == "x11":
env_patch["SDL_VIDEODRIVER"] = "x11"
# ── EGL 강제 (Wayland 환경 또는 Mesa 환경) ──────────────────
if display_server == "wayland" or "mesa" in opengl_info["renderer"].lower():
if not os.environ.get("SDL_VIDEO_X11_FORCE_EGL"):
env_patch["SDL_VIDEO_X11_FORCE_EGL"] = "1"
# ── 소프트웨어 렌더링 폴백 ───────────────────────────────────
# GPU 드라이버 없고 EGL도 없는 경우
if not opengl_info["has_glx"] and not opengl_info["has_egl"]:
print("[sdl_env] ⚠️ HW OpenGL 불가 → 소프트웨어 렌더링 폴백")
env_patch["LIBGL_ALWAYS_SOFTWARE"] = "1"
env_patch["SDL_RENDER_DRIVER"] = "software"
return env_patch
def apply_sdl_env(verbose: bool = True) -> dict[str, str]:
"""
Apply resolved SDL env vars to the current process environment
해결된 SDL 환경변수를 현재 프로세스에 적용
Must be called BEFORE importing pygame
pygame import 전에 반드시 호출해야 함
"""
patch = resolve_sdl_env()
for key, val in patch.items():
os.environ[key] = val
if verbose:
print(f"[sdl_env] SET {key}={val}")
return patch
사용법:
# ── main.py ──────────────────────────────────────────────────────
# IMPORTANT: apply_sdl_env() must be called before importing pygame
# 중요: pygame import 전에 반드시 apply_sdl_env() 호출
from sdl_env import apply_sdl_env
apply_sdl_env() # ← 여기서 먼저 설정
import pygame
from pygame.locals import *
from OpenGL.GL import *
def main():
pygame.init()
screen = pygame.display.set_mode(
(1280, 720),
DOUBLEBUF | OPENGL,
)
pygame.display.set_caption("pygame + OpenGL")
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
glClearColor(0.1, 0.1, 0.15, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
환경별 동작 요약:
| 환경 | 자동 설정 |
| X11 일반 | |
| Wayland 세션 | |
| SSH 원격 | |
| VM (VirtualBox 등) | |
| GPU 드라이버 없음 | |
imgui_bundle 과 함께 쓸 때:
from sdl_env import apply_sdl_env
apply_sdl_env() # hello_imgui.run() 전에 호출
from imgui_bundle import hello_imgui, imgui
# ...
hello_imgui.run(runner_params)
Troubleshooting
main() LINKER ERROR
아래와 같은 에러 메시지가 출력될 수 있다.
xxx error LNK2019: _WinMain@16 외부 기호(_WinMainCRTStartup 함수에서 참조)를 확인하지 못했습니다.
xxx fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.
SDL에서 main을 WinMain으로 Define하여 발생되는 에러이다. SDL.lib, SDLmain.lib 을 링크하면 된다.
MinGW에서 사용할 경우 아래와 같이 사용하면 된다.
implicit entry/start for main executable
- Stackoverflow: Why SDL defines main macro?
- Stackoverflow: SDL Error Undefined symbols for architecture x86_64 "_SDL_main"
clang에서 SDL을 사용할 경우 아래와 같은 에러 메시지가 출력될 수 있다.
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable.
maybe you meant: _SDL_main
ld: symbol(s) not found for architecture x86_64
이 경우, main이 매크로로 등록되어 나타나는 현상이다. 아래와 같이 매크로 등록을 해제한다.
Renderer already associated with window
SDL_GetError()를 통하여 아래와 같은 에러 메시지를 확인할 수 있다.
이 경우, 이미 해당 Window에서 Renderer를 생성했다는 의미이다. 이미 생성된 Renderer를 찾아봐야 한다.
MSYS DirectX Symbol error
MSYS에서 위와같이 설치할 경우 DirectX 관련 심볼(__in 등)을 찾을 수 없을 경우가 있다. 이 경우 DirectX를 정상적으로 설치해야 한다.
OpenGL.error.Error: Attempt to retrieve context when no valid context
Ubuntu 20.04 이상에서 Wayland 로 실행된다면 다음과 같은 에러가 출력될 수 있다:
pygame-ce 2.4.1 (SDL 2.28.5, Python 3.11.4)
/home/yourname/Project/ddrm/test.py:13: Warning: PyGame seems to be running through X11 on top of wayland, instead of wayland directly
...
OpenGL.error.Error: Attempt to retrieve context when no valid context
간단히, SDL_VIDEO_X11_FORCE_EGL=1 환경변수 설정하면 된다.
See also
Favorite site
- SDL website
- Wikipedia (en) SDL에 대한 설명
- libsdl-android (SDL library for Android, including several games)
SDL Wiki
Tutorial
- Lazy Foo' Productions (SDL Tutorial) 1
- SDL2: 01. 윈도우와 렌더러 (1)
- [추천] SDL Tutorial: Lesson 1 - SDL 설치 및 설정과 화면에 그림 띄우기
- Exploring SDL
- Transfer of SDL Game Framework Series. A part 1 — SDL Tutorial Basics
Guide
- AESOP Android 에서 SDL 사용하는 예제
- Using OpenGL With SDL
- SDL의 기초
- Empirical approach to CMAKE
- CMake를 이용하여 gtest 사용하기
- 게임개발을위한 SDL 라이브러리활용(2) 2
- SDL Tutorial Lesson 7: 글꼴
- sdl 코딩 #2 한글 출력하기
Link Third-party library
- wx-sdl: A tutorial on combining wxWidgets with SDL 3
- Demonstration of SDL2.0+FFmpeg player based on 4
- SDL GUI 툴킷 정리