Доступ ко всей видеопамяти через программирование OpenGL

Как получить доступ к видеопамяти видеокарты через программирование OpenGL, в частности, чтобы получить все содержимое видеопамяти?

Я пробовал следующие два метода, но потерпел неудачу. Прикрепив их, надеюсь, вы могли бы указать на ошибку в моей программе или в моем понимании устройства видеопамяти. Заранее спасибо!

Моя основная идея состоит в том, чтобы продолжать выделять неинициализированную область в видеопамяти до тех пор, пока не будет исследовано все содержимое видеопамяти.

(1) В основной функции я создаю окно с двойными буферами (см. следующие коды).

int main(int argc,char ** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); // double buffers
    glutInitWindowPosition(0,0);
    glutInitWindowSize(windowWidth, windowHeight);
    glutCreateWindow("Hope to be successful!");
    glutDisplayFunc(myDisplay); // call back function "myDisplay"
    glutKeyboardFunc(keyboard);
    glutMainLoop();

    free(PixelData);
    return 0;
}

Затем в функции «myDisplay» я сначала вызываю функцию glReadPixels() для считывания прямоугольника пикселей заданного размера из заднего буфера кадра, сохраняю информацию об этих пикселях в массиве «PixelData» и, наконец, отображаю эту информацию о пикселях на экран, вызвав функцию glDrawPixels(). После выполнения этой программы появляется только черное окно. Черный цвет по умолчанию. Это означает, что в окне ничего нет. Затем я попытался прочитать другие области из заднего фреймбуфера, и все они ничего не содержат.

Вывод из вышесказанного - в заднем фреймбуфере ничего не содержится. Однако это неразумно, потому что передний буфер должен содержать только текущее содержимое экрана/окно, и поэтому другие окна, открытые и свернутые в нижней части экрана, должны иметь свое содержимое в заднем фреймбуфере, но задний фреймбуфер пуст. Так где же хранятся эти окна (открытые и свернутые мной внизу)?

Я предполагаю, что фреймбуферы (задний и передний), выделенные для моей программы, занимают лишь небольшую часть всей видеопамяти. Таким образом, содержимое свернутого окна должно храниться в других местах видеопамяти.

Через некоторое время я прочитал введение в объект OpenGL frameBuffer (FBO), и там есть предложение: По умолчанию OpenGL использует фреймбуфер в качестве места назначения рендеринга, которое создается и полностью управляется оконной системой. Этот кадровый буфер по умолчанию называется кадровым буфером, предоставляемым оконной системой. Это, по-видимому, подтверждает мою догадку выше.

(2) Затем я начинаю работать над FBO в надежде, что FBO поможет мне исследовать все содержимое видеопамяти.

В приведенной ниже основной функции я создаю FBO и 7 объектов буфера рендеринга (RBO), а затем прикрепляю эти 7 RBO к этому FBO через точки привязки цвета.

const int RBO_COUNT = 7; //how many renderBuffer objects are created to attach to the frameBuffer object

int main(int argc, char **argv)
{
    ....
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_ALPHA); // display mode
    ...  

    // create a framebuffer object
    glGenFramebuffers(1, &fboId);
    glBindFramebuffer(GL_FRAMEBUFFER, fboId);

    //Create several 7 render buffer objects and attach all of them to the FBO.
    glGenRenderbuffers(RBO_COUNT, rbo);
    for (int i = 0; i < RBO_COUNT; i++)
    {
        glBindRenderbuffer(GL_RENDERBUFFER, rbo[i]);
        glRenderbufferStorage(GL_RENDERBUFFER, PIXEL_FORMAT, SCREEN_WIDTH, SCREEN_HEIGHT);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, colorAttach[i], GL_RENDERBUFFER, rbo[i]);
    }

   // check FBO status
   bool status = checkFramebufferStatus();
   if(!status) fboUsed = false;

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    ...

    glutMainLoop(); /* Start GLUT event-processing loop */
    return 0;
}

Ниже приведена основная часть моей функции обратного вызова дисплея. Его функция заключается в использовании клавиши пробела для управления тем, из какого объекта renderBuffer читать, а затем отображать его содержимое на экране.

void displayCB()
{
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

//read this FBO attached RBO, save its content to fboContent
//"count" is a global variable, and is incremented by 1 (mod )every time pressing the space key of the keyboard.
glReadBuffer(colorAttach[count]); 
glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_FORMAT, GL_UNSIGNED_BYTE, fboContent);

// back to normal window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind

// render to the default framebuffer //////////////////////////
glClear(GL_COLOR_BUFFER_BIT); // clear buffer
glClearColor(1, 0, 0, 1);
glDrawBuffer(GL_BACK);
glRasterPos2i(-1, -1);  
glDrawPixels(SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_FORMAT, GL_UNSIGNED_BYTE, fboContent);
glutSwapBuffers();
}

Окончательный результат разочаровывает. Содержимое всех объектов renderBuffer пусто. Я не знаю причину этого, потому что я думал, что все эти RBO никогда не были инициализированы и должны содержать некоторое оставшееся содержимое.


person loong    schedule 11.05.2012    source источник
comment
Я думал, что все эти RBO никогда не были инициализированы и должны содержать некоторое оставшееся содержимое. Тогда вам следует перечитать спецификацию. В нем говорится, что их содержимое не определено. Неопределенный может означать оставшееся содержимое. Это также может означать обнуление памяти. Это может означать, что для памяти установлен какой-то произвольный цвет, чтобы было легче отлавливать ошибки. Неопределенный означает неопределенный.   -  person Nicol Bolas    schedule 11.05.2012
comment
В спецификации (opengl.org/wiki/Renderbuffer_Object) сказано, что буфер рендеринга создается неинициализированным. Я думаю, вы правы. Являются ли неинициализированные RBO пустыми или содержат некоторое оставшееся содержимое, определяется временем создания этих RBO. Если вся видеопамять когда-то использовалась, а некоторые из них сейчас не распределены, вновь созданные RBO, вероятно, будут содержать какое-то предыдущее содержимое.   -  person loong    schedule 12.05.2012
comment
Это не спецификация; это статья из Вики. Спецификация находится в реестре OpenGL. Но спасибо за указание на ошибку; Я исправлю это.   -  person Nicol Bolas    schedule 12.05.2012
comment
Спасибо за ссылку на спец. Как вы думаете, подходит ли OpenGL для доступа ко всей видеопамяти? Ответ, предоставленный SigTerm, кажется разумным. Он сказал, что это может сделать только видеодрайвер, а OpenGL не может.   -  person loong    schedule 12.05.2012


Ответы (3)


Как получить доступ к видеопамяти видеокарты через программирование OpenGL, в частности, чтобы получить все содержимое видеопамяти?

Ты не можешь это делать. К необработанной видеопамяти нельзя получить доступ через OpenGL или DirectX. OpenGL имеет только различные «буферы». Единственное, что может получить к нему доступ, это видеодрайвер, который является проприетарным на платформе Windows. Свободной видеопамятью управляет видеодрайвер, и некоторые объекты в видеопамяти могут существовать только временно - драйвер может хранить копии в системной памяти, перемещать их и выгружать на диск при необходимости. Так что ваша идея управлять свободной памятью вручную не имеет практического применения.

У вас должна быть возможность доступа к видеопамяти непосредственно на СТАРОМ оборудовании — EGA/CGA/VGA, а также на картах, поддерживающих VESA, однако у вас не будет аппаратного ускорения, и вам нужно будет запустить что-то похожее на MS-DOS или иметь привилегии доступа к ядру/драйверу. Вы можете получить доступ к содержимому памяти в Linux, но я думаю, что это не поможет.

Я бы рекомендовал забыть об этой идее.

Вы имеете в виду, что OpenGL не может выполнить такую ​​задачу? На самом деле, я работал над этой проблемой почти два месяца.

Нечто подобное обычно происходит, когда вы начинаете грандиозный проект, не проведя предварительно достаточного количества исследований. Я бы рекомендовал учиться на этом опыте. Прежде чем приступить к написанию кода, всегда проверяйте, не было ли ваше приложение уже написано, имеет ли какое-либо практическое применение, может ли оно быть создано, есть ли потребность в этом приложении и достаточно ли у вас ресурсов для его создания.

В настоящее время управление объектами, хранящимися в видеопамяти, является работой водителя.

Если вы хотите увидеть объекты, созданные другими приложениями, вероятно, будет проще перехватить API OpenGL с помощью прокси-библиотек DLL, внедрения DLL или аналогичных методов и перехватить соответствующие вызовы.

person SigTerm    schedule 11.05.2012
comment
Спасибо за ваше подробное объяснение! Очень полезно! Для меня будет ужасно, если все, что вы сказали, окажется правдой. - person loong; 12.05.2012
comment
не обязательно старое оборудование; можно просто поместить приложение биоса на компакт-диск / дискету. все ПК поддерживают это. - person Dmitry; 15.08.2017

Как получить доступ к видеопамяти видеокарты через программирование OpenGL, в частности, чтобы получить все содержимое видеопамяти?

Говорите с операционной системой, а не с OpenGL.

person genpfault    schedule 11.05.2012
comment
Вы имеете в виду, что OpenGL не может выполнить такую ​​задачу? На самом деле, я работал над этой проблемой почти два месяца. Если OpenGL не сможет, мне придется перезапустить свою работу. Кроме того, не могли бы вы подробнее рассказать об общении с ОС? - person loong; 11.05.2012

Непонятно, почему вы хотите это сделать и какова ваша конечная цель, но мне кажется, что вы пытаетесь получить доступ к графической информации, созданной сторонними приложениями.

Если вы пытаетесь выполнить что делает FRAPS, имейте в виду, что он использует метод, совершенно отличный от того, что вы пытаетесь сделать (намного проще): он перехватывает вызовы графических библиотек, таких как OpenGL и DirectX.

person karlphillip    schedule 11.05.2012
comment
Я пытаюсь проверить, действительно ли возможна такая потенциальная атака. И доступ ко всей видеопамяти является частью процесса проверки. Спасибо за ответ. - person loong; 12.05.2012
comment
Ваша ссылка не работает. Можете ли вы попытаться исправить это (я имею в виду, вы можете найти обновленный URL-адрес?), поскольку в настоящее время меня интересует, как работает FRAPS, чтобы реализовать нечто подобное... - person leemes; 19.12.2012
comment
2 минуты поиска в интернете. :( Это фиксированный. - person karlphillip; 19.12.2012