부분 프레임 버퍼를 통한 메모리 사용 절감
This section explains, by exemplifying with a clock application, how to configure and use Partial Frame Buffers with a display with GRAM, to lower memory requirements at the expense of some performance.
STM32L4R9Discovery 평가 키트에서 실행되는 애플리케이션에 대한 동영상은 아래에서 확인할 수 있습니다
풀 사이즈 프레임 버퍼 메모리
일반적으로 프레임 버퍼는 디스플레이에서 사용 가능한 모든 픽셀을 수용할 만큼 충분한 용량을 갖춘 대형 메모리 배열입니다. 해상도가 480 x 272인 24비트 디스플레이에서 실행 중인 경우, 풀 사이즈 프레임 버퍼의 용량은 480 x 272 x 3바이트 = 391,680바이트입니다.
일부 애플리케이션에는 프레임 버퍼가 두 개("이중 버퍼링") 내지 세 개까지 있을 수 있습니다. 이 경우 총 메모리 요구 사항은 783,360바이트와 1,175,040바이트가 됩니다.
TouchGFX는 UI의 어떤 부분을 그릴 때 프레임 버퍼에 픽셀 값을 기록합니다. 모든 그리기 작업이 완료된 후에는 프레임 버퍼가 디스플레이로 전송됩니다. 보통 UI의 일부만 업데이트되는 경우에도 전체 프레임 버퍼가 디스플레이로 전송됩니다. 일반적으로 프레임 버퍼를 다수의 소형 블록에서 업데이트한 후 전송할 수 있습니다.
업데이트 1, 업데이트 2, 업데이트 3, ..., 업데이트 N, 디스플레이에 전송
경우에 따라 특히 외부 RAM이 없는 저가 솔루션에서는 애플리케이션의 나머지 부분이 프레임 버퍼와 함께 내부 RAM에 들어갈 수 있을 만큼 프레임 버퍼가 충분히 작아야 합니다. 이런 점에서는 부분 프레임 버퍼가 유용합니다.
부분 프레임 버퍼 메모리
부분 프레임 버퍼를 사용하면 TouchGFX 애플리케이션을 풀 사이즈보다 작은 몇 개의 프레임 버퍼로 실행할 수 있습니다. 프레임 버퍼의 수와 크기는 구성이 가능합니다. 이 기법은 애플리케이션의 메모리 요구 사항을 상당 부분 낮출 수 있지만, 다음과 같은 몇 가지 제약이 있습니다.
- 부분 프레임 버퍼는 내장 메모리가 있는 디스플레이에서만 작동합니다. 보통은 DSI 디스플레이나, 병렬 버스 연결(DBI 유형 A/B, 8080/6800) 또는 SPI 버스 연결이 있는 디스플레이에서 작동합니다.
- 복잡한 애플리케이션에서는 깨짐 현상이 발생할 수 있습니다.
부분 프레임 버퍼는 프레임 버퍼를 사용해 디스플레이에 모든 픽셀을 표시하기 보다는 일반적으로 더 작은 부분을 표시합니다. 이 문서에서 사용된 클록 예제에서는 각각 11,700바이트의 프레임 버퍼 세 개가 사용되었습니다. 따라서 프레임 버퍼의 메모리 점유율은 35,100바이트가 됩니다.
애플리케이션에서 UI의 일부를 업데이트해야 할 때마다 TouchGFX는 구성된 부분 프레임 버퍼 중 하나를 선택하고, 부분 프레임 버퍼에서 그리기 작업을 완료한 다음, 해당 부분을 디스플레이에 전송합니다. 렌더링이 필요한 UI의 모든 영역에서 이 작업이 반복됩니다. 이렇게 하면 데이터 업데이트 및 전송 공식이 다음과 같이 변경됩니다.
Update1, Transfer1, Update2, Transfer2, Update3, Transfer3, ..., UpdateN, TransferN
어떤 경우에는 다음 버퍼의 업데이트가 실행되는 동안 한 부분 프레임 버퍼의 전송이 실행될 수 있습니다.
디스플레이 깨짐 현상
풀 사이즈 프레임 버퍼를 사용하는 경우에 반해 부분 프레임을 사용하는 경우에는 TouchGFX가 업데이트 되는 즉시 UI의 일부를 전송하게 됩니다. 디스플레이가 주기적으로 새로 고침이 되어야 하기 때문에 최대 16ms(60fps 디스플레이의 경우) 후에 디스플레이의 표면에 수신된 업데이트가 표시됩니다. 이로 인해 모든 업데이트가 전송되기 전에 디스플레이에 대한 첫 번째 업데이트가 사용자에게 표시될 수 있습니다.
그리기 작업 및 전송의 전체 시퀀스를 완료하는 데 시간이 오래 걸리는 경우(> 16ms) 사용자에게 이전 프레임과 일부 새로운 업데이트의 조합이 표시될 가능성이 높습니다. 이를 디스플레이 깨짐 현상이라고 하며, 이러한 현상이 발생하는 것은 바람직하지 않습니다. 이러한 이유로 부분 프레임 버퍼는 렌더링에 오랜 시간이 걸리는 복잡한 애니메이션을 사용하는 애플리케이션에는 적합하지 않습니다.
디스플레이 업데이트 예제
애플리케이션에서 부분 프레임 버퍼를 구성하는 방법을 알아보기 전에 원호가 초 단위로 움직이는 디지털 시계를 예로 들어 살펴보겠습니다. 녹색 원호는 초당 6도씩 움직이며, 1분 후에 완전히 회전합니다. 아래 이미지에서와 같이 UI는 4개의 위젯으로 구성되어 있습니다.
다음은 디지털 시계와 원호를 업데이트하는 코드입니다.
MainView.cpp
void MainView::handleTickEvent()
{
ticks++;
if (ticks == 10)
{
ticks = 0;
secs += 1;
if (secs == 60) //increment minutes
{
secs = 0;
min += 1;
if (min == 60) //increment hours
{
min = 0;
hour += 1;
if (hour == 24)
{
hour = 0;
}
}
//Only update digital clock when minutes or hours change
digitalClock.setTime24Hour(hour, min, secs);
}
//Always update seconds
circleSeconds.updateArc(secs*6 - 20, secs*6);
}
}
다음 이미지는 원호가 상단에 접근하고 디지털 시계가 업데이트될 때 처음 몇 초 동안 업데이트되는 영역을 보여줍니다(회색 직사각형). 처음 두 프레임에서는 초만 변경됩니다(58초 및 59초). 세 번째 프레임에서 60초에 도달하면 시와 분 텍스트가 업데이트됩니다.
위의 세 번째 이미지에서 업데이트된 사각형은 154 x 60 픽셀, 20 x 12 픽셀 및 33 x 8 픽셀입니다. 표준 프레임 버퍼를 사용할 때 이러한 세 개의 직사각형이 전체 프레임 버퍼에 그려지고(이전 픽셀 덮어쓰기), 나중에 디스플레이로 전송됩니다. 부분 프레임 버퍼를 사용할 때 이들 세 개의 직사각형은 자체의 작은 프레임 버퍼에 그려진 다음, 즉시 디스플레이로 전송되어 표시됩니다.
부분 프레임 버퍼 구성
The following steps are required for TouchGFX to use partial frame buffers:
- 메모리 버퍼를 이용해 프레임 버퍼 할당자 객체 생성
- 해당 할당자를 사용하도록 TouchGFX HAL 클래스를 구성
- 버퍼를 디스플레이로 전송하는 코드를 작성
1단계와 2단계는 STM32CubeMX를 통해 TouchGFX Generator에서 자동으로 생성되는 반면, 3단계는 픽셀을 디스플레이로 전송하는 독점 드라이버입니다.
Further reading
An example configuration with 3 partial framebuffer block of size 1920bytes used to draw the updates areas from the above section is shown below.
먼저, 작은 원 업데이트를 그리기 위해 할당된 두 프레임 버퍼의 위치와 크기(위의 두 번째 이미지)를 확인합니다(24Bpp로 가정).
직사각형 | x | y | 너비 | 높이 | 픽셀 |
---|---|---|---|---|---|
직사각형 1 | 112 | 56 | 22 | 14 | 308 픽셀 = 924 바이트 |
직사각형 2 | 153 | 42 | 29 | 11 | 319 픽셀 = 957 바이트 |
두 직사각형 모두 크기가 작기 때문에 프레임 버퍼 할당자가 할당한 블록에 들어갈 수 있습니다.
위의 세 번째 이미지에는 원에 대한 작은 업데이트와 텍스트를 덮는 더 큰 직사각형 등 세 개의 업데이트된 직사각형이 나와 있습니다.
직사각형 | x | y | 너비 | 높이 | 픽셀 |
---|---|---|---|---|---|
직사각형 1 | 126 | 51 | 20 | 12 | 240 픽셀 = 720 바이트 |
직사각형 2 | 165 | 42 | 33 | 8 | 264 픽셀 = 792 바이트 |
직사각형 3 | 118 | 165 | 154 | 60 | 9,240픽셀 = 27,720바이트 |
다시 말해, 직사각형 1과 2는 너무 작아서 프레임 버퍼 할당자가 할당한 블록에 들어갈 수 있지만 프레임 버퍼 3은 크기가 너무 큽니다. 이 직사각형은 너무 커서 프레임 버퍼(11,700바이트)에 들어갈 수 있는 여러 개의 직사각형으로 분할됩니다.
여기서 우리는 세 개의 직사각형을 업데이트하지만, 할당자는 두 개의 블록만 갖게 됩니다. 이 상황에서 TouchGFX는 첫 번째 블록들이 전송될 때까지 기다렸다가 블록을 재사용합니다.
프레임 버퍼를 화면으로 전송
The implementation of the code to transfer partial framebuffer blocks to the display depends on the display interface use. For examples on how this can be done, see the following articles:
결론
이 문서에서는 부분 프레임 버퍼 전략이 프레임 버퍼 메모리가 통합된 디스플레이를 갖춘 플랫폼의 메모리 요구 사항을 낮추는 데 어떤 도움이 되는지 살펴봤습니다.